From 6e92af38754491c1d98dcfb8bbc27ae0fb6407f1 Mon Sep 17 00:00:00 2001 From: Manolo Carrasco Date: Fri, 23 Sep 2011 14:19:02 +0000 Subject: [PATCH] use JSON.parse when available when parsing properties to avoid security issues --- .../google/gwt/query/client/Properties.java | 29 ++++++++++--------- .../google/gwt/query/client/js/JsUtils.java | 6 +++- .../gwt/query/client/JreQueryCoreTest.java | 28 ++++++------------ 3 files changed, 30 insertions(+), 33 deletions(-) diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java index 3aefed30..125981e8 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java @@ -18,6 +18,7 @@ package com.google.gwt.query.client; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArrayMixed; import com.google.gwt.query.client.js.JsCache; +import com.google.gwt.query.client.js.JsUtils; /** * JSO for accessing Javascript objective literals used by GwtQuery functions. @@ -25,14 +26,14 @@ import com.google.gwt.query.client.js.JsCache; public class Properties extends JavaScriptObject { public static Properties create() { - return createImpl("({})"); + return JsCache.create().cast(); } public static Properties create(String properties) { if (properties != null && !properties.isEmpty()) { String p = wrapPropertiesString(properties); try { - return createImpl("({" + p + "})"); + return JsUtils.parseJSON(p); } catch (Exception e) { System.err.println("Error creating Properties: \n> " + properties + "\n< " + p + "\n" + e.getMessage()); } @@ -40,24 +41,26 @@ public class Properties extends JavaScriptObject { return create(); } - public static final native Properties createImpl(String properties) /*-{ - return eval(properties); - }-*/; - public static String wrapPropertiesString(String s) { String ret = s // .replaceAll("\\s*/\\*[\\s\\S]*?\\*/\\s*", "") // Remove comments .replaceAll("([:\\)\\(,;}{'\"])\\s+" , "$1") // Remove spaces .replaceAll("\\s+([:\\)\\(,;}{'\"])" , "$1") // Remove spaces - .replaceFirst("^[{\\(]+(|.*[^}\\)])[}\\)]+$", "$1") // Remove ({}) - .replaceAll("\\(\"([^\\)]+)\"\\)" , "($1)") // Remove quotes - .replaceAll(",+([\\w-]+:+)" , ";$1") // put semicolon - .replaceAll(":\\s*[\"']?([^'\"\\]};]*)[\"']?\\s*(;+|$)", ":\"$1\",") // put quotes to all values (even empty) - .replaceAll("(^|[^\\w-$'])([\\w-]+):\"", "$1\"$2\":\"") // quote keys + .replaceFirst("^[\\(]+(.*)[\\)]+$", "$1") // Remove () + .replaceAll("\\([\"']([^\\)]+)[\"']\\)" , "($1)") // Remove quotes + .replaceAll("[;,]+([\\w-]+):", ";$1:") // Change comma by semicolon + .replaceAll("([^,;])([\\]}])", "$1;$2") // Put control semicolon used below + .replaceAll(":\\s*[\"']?([^;\\{\\}\\[\\]\"']*)[\"']?\\s*([;,]+|$)", ":\"$1\";") // put quotes to all values (even empty) + .replaceAll("[;,]+([\\w-]+):", ";$1:") // Change semicolon by comma + .replaceAll("(^|[^\\w-$'])([\\w-]+):(['\"\\[{])", "$1\"$2\":$3") // quote keys + .replaceAll("(^|[^\\w-$'])([\\w-]+):(['\"\\[{])", "$1\"$2\":$3") // quote keys second pass + .replaceAll("(|[\\[\\]\\{\\},\\(])'([^']*)'", "$1\"$2\"") // Replace single-quote by double-quote .replaceAll(";([^:]+):", ",$1:") // change semicolon - .replaceAll(":\"(-?[\\d\\.]+|null|false|true)\",", ":$1,") // numbers do not need quote - .replaceFirst("[,]+$", "") // remove endings + .replaceAll(";([^:]+):", ",$1:") // change semicolon second pass + .replaceAll(":\"(-?[\\d\\.]+|null|false|true)\"[;,]", ":$1,") // numbers do not need quote + .replaceAll("[;,]+([\\]\\}]|$)", "$1") // remove endings ; + ret = ret.matches("(^[\\[\\{].*[\\]\\}]$)") ? ret : "{" + ret + "}"; return ret; } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java index 4145dd1e..bb923dcf 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java @@ -73,9 +73,13 @@ public class JsUtils { public Properties parseJSON(String json) { // No checks to the passed string so json should be // a well-formed json string. - return Properties.createImpl(json); + return evalImpl("(" + json + ")"); } + public static final native Properties evalImpl(String properties) /*-{ + return eval(properties); + }-*/; + @Override public native String XML2String(JavaScriptObject o) /*-{ return o.xml; diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/JreQueryCoreTest.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/JreQueryCoreTest.java index 2b3d7c00..e91190fb 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/JreQueryCoreTest.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/JreQueryCoreTest.java @@ -34,32 +34,22 @@ public class JreQueryCoreTest extends GWTTestCase { } public void testWrapPropertiesString() { - assertEquals("({})", Properties + assertEquals("{}", Properties .wrapPropertiesString("")); - assertEquals("({})", Properties + assertEquals("{}", Properties .wrapPropertiesString("({})")); - assertEquals("({border:'1px solid black'})", Properties + assertEquals("{\"border\":\"1px solid black\"}", Properties .wrapPropertiesString("border:'1px solid black'")); - assertEquals("({border:'1px solid black'})", Properties - .wrapPropertiesString("(border:'1px solid black')")); - assertEquals("({border:'1px solid black'})", Properties - .wrapPropertiesString("{border:'1px solid black'}")); - assertEquals("({border:'1px solid black'})", Properties - .wrapPropertiesString("{border:'1px solid black'}")); - assertEquals("({border:'1px solid black'})", Properties - .wrapPropertiesString("(border:'1px solid black')")); - assertEquals("({border:'1px solid black'})", Properties - .wrapPropertiesString("{(border:'1px solid black')}")); - assertEquals("({border:'1px solid black'})", Properties - .wrapPropertiesString("({border:'1px solid black'})")); - assertEquals("({b:'a',c:1,d:'url(https://test.com)',e:null,f:false})", Properties + assertEquals("{\"b\":\"a\",\"c\":1,\"d\":\"url(https://test.com)\",\"e\":null,\"f\":false}", Properties .wrapPropertiesString("b: 'a'; c: 1, /*gg: aadf*/d: url('https://test.com');,e:null,f:false")); - assertEquals("({color:'rgb(0,0,139)',background:'red'})", Properties + assertEquals("{\"color\":\"rgb(0,0,139)\",\"background\":\"red\"}", Properties .wrapPropertiesString("color: 'rgb(0, 0,139)', background: red")); - assertEquals("({width:'',top:''})", Properties + assertEquals("{\"width\":\"\",\"top\":\"\"}", Properties .wrapPropertiesString("width: '' ; top:'' ;")); - assertEquals("({'border-left':'solid'})", Properties + assertEquals("{\"border-left\":\"solid\"}", Properties .wrapPropertiesString("border-left: solid")); + assertEquals("[{\"a\":1,\"b\":{\"a\":2,\"b\":{\"a\":3}},\"u\":\"url\",\"d\":2,\"t\":[\"hola\",\"adios\"],\"z\":true}]", Properties + .wrapPropertiesString("[{a:1, b:{a:2,b:{a:3}},u:url, d:'2','t':['hola','adios'], 'z': true}]")); } } -- 2.39.5