From 01b68c51052514681287dd63e8e713742c42cd0c Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 3 May 2011 10:48:24 +0300 Subject: [PATCH] Bug #12375190: UPDATEXML CRASHES ON SIMPLE INPUTS The XPATH implementation was not handling correctly the XPATH production #19 (http://www.w3.org/TR/1999/REC-xpath-19991116/#node-sets), namely PathExpr ::= | FilterExpr '/' RelativeLocationPath | FilterExpr '//' RelativeLocationPath It was lacking context for the RelativeLocationPath and it was just ignoring the second slash instead of treating it as a different axis specifier. Fixed the above two problems and added a test case. --- mysql-test/r/xml.result | 18 ++++++++++++++++++ mysql-test/t/xml.test | 9 +++++++++ sql/item_xmlfunc.cc | 21 +++++++++++++++++++-- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/xml.result b/mysql-test/r/xml.result index 8ca9ab84bf7..30aa77ddf37 100644 --- a/mysql-test/r/xml.result +++ b/mysql-test/r/xml.result @@ -1144,5 +1144,23 @@ SELECT UPDATEXML(CONVERT('' USING swe7), TRUNCATE('',1), 0); UPDATEXML(CONVERT('' USING swe7), TRUNCATE('',1), 0) NULL # +# Bug#12375190: UPDATEXML CRASHES ON SIMPLE INPUTS +# +SELECT UPDATEXML('','(a)/a',''); +UPDATEXML('','(a)/a','') + +SELECT UPDATEXML('x','(a)/a',''); +UPDATEXML('x','(a)/a','') + +SELECT UPDATEXML('x','(a)/a',''); +UPDATEXML('x','(a)/a','') +x +SELECT UPDATEXML('x','(a)//a',''); +UPDATEXML('x','(a)//a','') + +SELECT ExtractValue('aabb','(a)/a|(a)/b'); +ExtractValue('aabb','(a)/a|(a)/b') +aa bb +# # End of 5.5 tests # diff --git a/mysql-test/t/xml.test b/mysql-test/t/xml.test index 89c0b8992b1..b36bd2067cc 100644 --- a/mysql-test/t/xml.test +++ b/mysql-test/t/xml.test @@ -664,6 +664,15 @@ SELECT ExtractValue(CONVERT('<\"', BINARY(10)), 1); SET NAMES latin1; SELECT UPDATEXML(CONVERT('' USING swe7), TRUNCATE('',1), 0); +--echo # +--echo # Bug#12375190: UPDATEXML CRASHES ON SIMPLE INPUTS +--echo # +SELECT UPDATEXML('','(a)/a',''); +SELECT UPDATEXML('x','(a)/a',''); +SELECT UPDATEXML('x','(a)/a',''); +SELECT UPDATEXML('x','(a)//a',''); +SELECT ExtractValue('aabb','(a)/a|(a)/b'); + --echo # --echo # End of 5.5 tests --echo # diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index 49d18b1bb0f..531b9e11cb5 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -1973,6 +1973,9 @@ static int my_xpath_parse_UnionExpr(MY_XPATH *xpath) static int my_xpath_parse_FilterExpr_opt_slashes_RelativeLocationPath(MY_XPATH *xpath) { + Item *context= xpath->context; + int rc; + if (!my_xpath_parse_FilterExpr(xpath)) return 0; @@ -1986,8 +1989,22 @@ my_xpath_parse_FilterExpr_opt_slashes_RelativeLocationPath(MY_XPATH *xpath) return 0; } - my_xpath_parse_term(xpath, MY_XPATH_LEX_SLASH); - return my_xpath_parse_RelativeLocationPath(xpath); + /* + The context for the next relative path is the nodeset + returned by FilterExpr + */ + xpath->context= xpath->item; + + /* treat double slash (//) as /descendant-or-self::node()/ */ + if (my_xpath_parse_term(xpath, MY_XPATH_LEX_SLASH)) + xpath->context= new Item_nodeset_func_descendantbyname(xpath->context, + "*", 1, xpath->pxml, 1); + rc= my_xpath_parse_RelativeLocationPath(xpath); + + /* push back the context and restore the item */ + xpath->item= xpath->context; + xpath->context= context; + return rc; } static int my_xpath_parse_PathExpr(MY_XPATH *xpath) {