2007-10-18 Eric Seidel <eric@webkit.org>
authoreseidel <eseidel@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 18 Oct 2007 07:30:13 +0000 (07:30 +0000)
committereseidel <eseidel@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 18 Oct 2007 07:30:13 +0000 (07:30 +0000)
        Reviewed by Maciej.

        Fix crashers in SVGViewSpec::parseViewSpec
        http://bugs.webkit.org/show_bug.cgi?id=15504

        Test is blocked by bug 15503, landed as:
        * svg/dom/viewspec-parser.html-disabled

        * bindings/scripts/CodeGeneratorObjC.pm: support classes where all parents are interfaces
        * ksvg2/svg/SVGViewSpec.cpp:
        (WebCore::SVGViewSpec::parseViewSpec):
        * ksvg2/svg/SVGViewSpec.idl: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@26740 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/js/resources/js-test-post.js
LayoutTests/fast/js/resources/js-test-pre.js
LayoutTests/svg/dom/viewspec-parser.html-disabled [new file with mode: 0644]
WebCore/ChangeLog
WebCore/bindings/scripts/CodeGeneratorObjC.pm
WebCore/ksvg2/svg/SVGViewSpec.cpp
WebCore/ksvg2/svg/SVGViewSpec.idl [new file with mode: 0644]

index 606e2e0..8a169c3 100644 (file)
@@ -1,3 +1,15 @@
+2007-10-18  Eric Seidel  <eric@webkit.org>
+
+        Reviewed by Maciej.
+        
+        Test case for http://bugs.webkit.org/show_bug.cgi?id=15504
+        Landed -disabled as it's blocked by:
+        http://bugs.webkit.org/show_bug.cgi?id=15503
+
+        * fast/js/resources/js-test-post.js: add support for XHTML
+        * fast/js/resources/js-test-pre.js: add support for XHTML
+        * svg/dom/viewspec-parser.html-disabled: Added.
+
 2007-10-17  Rob Buis  <buis@kde.org>
 
         Reviewed by Darin, Adam, and Maciej.
index 72ba76f..6d8a68f 100644 (file)
@@ -1,2 +1,2 @@
 shouldBeTrue("successfullyParsed");
-debug('<br><span class="pass">TEST COMPLETE</span>');
\ No newline at end of file
+debug('<br /><span class="pass">TEST COMPLETE</span>');
index 26d7d5a..d11d2bc 100644 (file)
@@ -16,8 +16,8 @@ function description(msg)
 function debug(msg)
 {
     var span = document.createElement("span");
-    span.innerHTML = msg + '<br>';
-    document.getElementById("console").appendChild(span);
+    document.getElementById("console").appendChild(span); // insert it first so XHTML knows the namespace
+    span.innerHTML = msg + '<br />';
 }
 
 function escapeHTML(text)
@@ -27,12 +27,12 @@ function escapeHTML(text)
 
 function testPassed(msg)
 {
-    debug('<span class="pass">PASS</span> ' + escapeHTML(msg) + '</span>');
+    debug('<span><span class="pass">PASS</span> ' + escapeHTML(msg) + '</span>');
 }
 
 function testFailed(msg)
 {
-    debug('<span class="fail">FAIL</span> ' + escapeHTML(msg) + '</span>');
+    debug('<span><span class="fail">FAIL</span> ' + escapeHTML(msg) + '</span>');
 }
 
 function areArraysEqual(_a, _b)
diff --git a/LayoutTests/svg/dom/viewspec-parser.html-disabled b/LayoutTests/svg/dom/viewspec-parser.html-disabled
new file mode 100644 (file)
index 0000000..dac5cd7
--- /dev/null
@@ -0,0 +1,178 @@
+<html>
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+<script src="resources/scripted-random.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+    description("This test fuzzes the transform parser with semi-random attribute values and dumps the results of any values that parse successfully.");
+
+    var attributes = { // maps a viewspec attribute to its minimum argument count
+        viewBox: 6,
+        preserveAspectRatio: 1,
+        transform: 1,
+        zoomAndPan: 1,
+        viewTarget: 1
+    };
+    
+    var preserveAspectRatioValues = [ "Min", "Max", "Mid" ];
+    
+    var testsToRun = [
+      "svgView",
+      "svgView(",
+      "svgView()",
+      "svgView(" + String.fromCharCode(0),
+      "svgView(" + String.fromCharCode(0) + ")",
+      "svgView(transform(scale(2));;)",
+      "svgView(transform(scale(2));x", // used to hang
+      "svgView(transform(scale(.5)))",
+      "svgView(;transform(scale(.5)))",
+      "svgView(;;transform(scale(.5)))",
+      "svgView(transform(scale(.5));transform(scale(2));transform(scale(2)))",
+      ];
+    
+    
+    var characters = [
+        "0",
+        "1",
+        "2",
+        "3",
+        "4",
+        "5",
+        "6",
+        "7",
+        "8",
+        "9",
+        ".",
+        "e",
+        "+",
+        "-",
+        "e",
+        "(",
+        ")",
+        " ", // not a valid fragment char
+        "\t", // not a valid fragment char
+        ","
+    ];
+    
+    function buildTestsToRun() {
+      for (var attribute in attributes) {
+
+          // Too few / too many arguments
+          for (var i = 0; i < 20; i++) { //>
+              var attributeString = "svgView(" + attribute + "(";
+              for (var j = 0; j < i; j++) { //>
+                  attributeString += "0";
+                  if (j < i - 1) //>
+                      attributeString += ",";
+              }
+              attributeString += "))";
+              testsToRun.push(attributeString);
+          }
+
+          // Random assortments of valid characters
+          for (var i = 0; i < 100; i++) { //>
+              var attributeString = "svgView(" + attribute + "(";
+              var count = Math.scriptedRandomInt(20);
+              for (var j = 0; j < count; j++) { //>
+                  attributeString += characters[Math.scriptedRandomInt(characters.length)];
+              }
+              testsToRun.push(attributeString);
+          }
+          
+          // attribute names that are "off by one"
+          var extraChar = attribute.charAt(attribute.length - 1);
+          testsToRun.push("svgView(" + attribute + extraChar + "(0, 0)");
+          testsToRun.push("svgView(" + attribute.substring(0, attribute.length - 1) + "(0, 0)");
+          
+          // Empty-ish attributes
+          testsToRun.push("svgView(" + attribute);
+          testsToRun.push("svgView(" + attribute + String.fromCharCode(0));
+          testsToRun.push("svgView(" + attribute + "(" + String.fromCharCode(0) + ")");
+      }
+      
+    }
+    
+    function viewSpecToString(viewSpec)
+    {
+        if (!viewSpec)
+          return viewSpec;
+        
+        var attributes = [];
+        if (viewSpec.transform)
+          attributes.push("transform(" + viewSpec.transform + ")");
+        if (viewSpec.viewBox)
+          attributes.push("viewBox(" + viewSpec.viewBox + ")");
+        if (viewSpec.preserveAspectRatio)
+          attributes.push("preserveAspectRatio(" + viewSpec.preserveAspectRatio + ")");
+        if (viewSpec.zoomAndPan)
+          attributes.push("zoomAndPan(" + viewSpec.zoomAndPan + ")");
+        if (viewSpec.viewTarget)
+          attributes.push("viewTarget(" + viewSpac.viewTarget + ")");
+          
+        return "svgView(" + attributes.join(";") + ")";
+    }
+    
+    var testNumber = 0;
+    var testString = "[initial view]"
+    
+    function makeURLRelative(url) {
+      return url.slice(url.indexOf("resources"));
+    }
+
+    function testFragment(string) {
+      var oldEmbed = document.getElementById("object");
+      if (oldEmbed) {
+        oldEmbed.parentNode.removeChild(oldEmbed);
+      }
+      var embedElement = document.createElement("iframe");
+      embedElement.setAttribute("id", "object");
+      embedElement.setAttribute("width", "100");
+      embedElement.setAttribute("height", "100");
+      embedElement.setAttribute("onload", "continueFuzzing(event)");
+      var newURL = "resources/viewspec-parser.svg#" + string;
+      embedElement.src = newURL;
+      debug("Starting: " + makeURLRelative(embedElement.src));
+      document.body.appendChild(embedElement);
+    }
+
+    function startNextTest()
+    {
+      testFragment(testString);
+    }
+    
+    function continueFuzzing(event)
+    {
+        var embedElement = document.getElementById("object");
+        if (embedElement.contentDocument) {
+          debug("Loaded:   " + makeURLRelative(embedElement.contentDocument.URL));
+          debug("Parsed: " + viewSpecToString(embedElement.contentDocument.currentView) + " from: " + testString);      
+        } else
+          debug("no svgdocument");
+        
+        if (testNumber < testsToRun.length)
+          testString = testsToRun[testNumber];
+        else {
+          var scriptTag = document.createElement("script");
+          scriptTag.src = "../../fast/js/resources/js-test-post.js";
+          document.body.appendChild(scriptTag);
+          if (window.layoutTestController)
+            layoutTestController.notifyDone();
+          return;
+        }
+        testNumber++;
+        
+        // this lets us out of the onload handler so we don't overrun the stack
+        window.setTimeout(startNextTest, 0);
+    }
+    if (window.layoutTestController)
+      layoutTestController.waitUntilDone();
+    
+    buildTestsToRun();
+    testFragment("");
+    successfullyParsed = true;
+</script>
+</html>
index 7ac63c4..342b11d 100644 (file)
@@ -1,3 +1,18 @@
+2007-10-18  Eric Seidel  <eric@webkit.org>
+
+        Reviewed by Maciej.
+
+        Fix crashers in SVGViewSpec::parseViewSpec
+        http://bugs.webkit.org/show_bug.cgi?id=15504
+
+        Test is blocked by bug 15503, landed as:
+        * svg/dom/viewspec-parser.html-disabled
+
+        * bindings/scripts/CodeGeneratorObjC.pm: support classes where all parents are interfaces
+        * ksvg2/svg/SVGViewSpec.cpp:
+        (WebCore::SVGViewSpec::parseViewSpec):
+        * ksvg2/svg/SVGViewSpec.idl: Added.
+
 2007-10-17  Rob Buis  <buis@kde.org>
 
         Reviewed by Darin, Adam, and Maciej.
index ee6f99f..2b9113d 100644 (file)
@@ -204,7 +204,7 @@ sub finish
 }
 
 # Uppercase the first letter, while respecting WebKit style guidelines. 
-# E.g., xmlEncoding becomes XMLEncoding, but xmlllang becomes Xmllang.
+# E.g., xmlEncoding becomes XMLEncoding, but xmllang becomes Xmllang.
 sub WK_ucfirst
 {
     my $param = shift;
@@ -386,6 +386,9 @@ sub GetParentAndProtocols
         my $firstParent = $codeGenerator->StripModule(shift(@parents));
         if (IsProtocolType($firstParent)) {
             push(@protocols, "DOM" . $firstParent);
+            if (!$isProtocol) {
+                $parent = "DOMObject";
+            }
         } else {
             $parent = "DOM" . $firstParent;
         }
index e3aeefa..4e469d3 100644 (file)
@@ -99,30 +99,30 @@ bool SVGViewSpec::parseViewSpec(const String& viewSpec)
     if (!skipString(currViewSpec, end, svgViewSpec, sizeof(svgViewSpec) / sizeof(UChar)))
         return false;
 
-    if (*currViewSpec != '(' )
+    if (currViewSpec >= end || *currViewSpec != '(' )
         return false;
     currViewSpec++;
 
-    while (*currViewSpec != ')' && currViewSpec < end) {
+    while (currViewSpec < end && *currViewSpec != ')') {
         if (*currViewSpec == 'v') {
             if (skipString(currViewSpec, end, viewBoxSpec, sizeof(viewBoxSpec) / sizeof(UChar))) {
-                if (*currViewSpec != '(')
+                if (currViewSpec >= end || *currViewSpec != '(')
                     return false;
                 currViewSpec++;
                 float x, y, w, h;
                 if (!parseViewBox(currViewSpec, end, x, y, w, h, false))
                     return false;
                 setViewBoxBaseValue(FloatRect(x, y, w, h));
-                if (*currViewSpec != ')')
+                if (currViewSpec >= end || *currViewSpec != ')')
                     return false;
                 currViewSpec++;
             } else if (skipString(currViewSpec, end, viewTargetSpec, sizeof(viewTargetSpec) / sizeof(UChar))) {
-                if (*currViewSpec != '(')
+                if (currViewSpec >= end || *currViewSpec != '(')
                     return false;
                 const UChar* viewTargetStart = ++currViewSpec;
-                while (*currViewSpec != ')' && currViewSpec <= end)
+                while (currViewSpec < end && *currViewSpec != ')')
                     currViewSpec++;
-                if (currViewSpec > end)
+                if (currViewSpec >= end)
                     return false;
                 setViewTargetString(String(viewTargetStart, currViewSpec - viewTargetStart));
                 currViewSpec++;
@@ -131,44 +131,43 @@ bool SVGViewSpec::parseViewSpec(const String& viewSpec)
         } else if (*currViewSpec == 'z') {
             if (!skipString(currViewSpec, end, zoomAndPanSpec, sizeof(zoomAndPanSpec) / sizeof(UChar)))
                 return false;
-            if (*currViewSpec != '(')
+            if (currViewSpec >= end || *currViewSpec != '(')
                 return false;
             currViewSpec++;
             if (!parseZoomAndPan(currViewSpec, end))
                 return false;
-            if (*currViewSpec != ')')
+            if (currViewSpec >= end || *currViewSpec != ')')
                 return false;
             currViewSpec++;
         } else if (*currViewSpec == 'p') {
             if (!skipString(currViewSpec, end, preserveAspectRatioSpec, sizeof(preserveAspectRatioSpec) / sizeof(UChar)))
                 return false;
-            if (*currViewSpec != '(')
+            if (currViewSpec >= end || *currViewSpec != '(')
                 return false;
             currViewSpec++;
             if (!preserveAspectRatioBaseValue()->parsePreserveAspectRatio(currViewSpec, end, false))
                 return false;
-            if (*currViewSpec != ')')
+            if (currViewSpec >= end || *currViewSpec != ')')
                 return false;
             currViewSpec++;
         } else if (*currViewSpec == 't') {
             if (!skipString(currViewSpec, end, transformSpec, sizeof(transformSpec) / sizeof(UChar)))
                 return false;
-            if (*currViewSpec != '(')
+            if (currViewSpec >= end || *currViewSpec != '(')
                 return false;
             currViewSpec++;
             SVGTransformable::parseTransformAttribute(m_transform.get(), currViewSpec, end);
-            if (*currViewSpec != ')')
+            if (currViewSpec >= end || *currViewSpec != ')')
                 return false;
             currViewSpec++;
-        }
+        } else
+            return false;
 
-        if (*currViewSpec == ';')
+        if (currViewSpec < end && *currViewSpec == ';')
             currViewSpec++;
     }
-    if (currViewSpec >= end)
-        return false;
-
-    if (*currViewSpec != ')')
+    
+    if (currViewSpec >= end || *currViewSpec != ')')
         return false;
 
     return true;
diff --git a/WebCore/ksvg2/svg/SVGViewSpec.idl b/WebCore/ksvg2/svg/SVGViewSpec.idl
new file mode 100644 (file)
index 0000000..46d4c8e
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+module svg {
+
+    interface [Conditional=SVG, ObjCCustomInternalImpl] SVGViewSpec : SVGZoomAndPan, SVGFitToViewBox
+    {
+          readonly attribute SVGTransformList transform;
+          readonly attribute SVGElement       viewTarget;
+          readonly attribute DOMString        viewBoxString;
+          readonly attribute DOMString        preserveAspectRatioString;
+          readonly attribute DOMString        transformString;
+          readonly attribute DOMString        viewTargetString;
+    };
+
+}