php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #44251 Question mark and an escaped singel quote lead to an exception
Submitted: 2008-02-26 11:11 UTC Modified: 2008-10-10 12:18 UTC
Votes:11
Avg. Score:4.8 ± 0.4
Reproduced:10 of 10 (100.0%)
Same Version:7 (70.0%)
Same OS:6 (60.0%)
From: om at viazenetti dot de Assigned: felipe (profile)
Status: Closed Package: PDO related
PHP Version: 5.2.5 OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: om at viazenetti dot de
New email:
PHP Version: OS:

 

 [2008-02-26 11:11 UTC] om at viazenetti dot de
Description:
------------
If a question mark and an escaped singel quote appear in a where statement as value, the PDO method prepare tries to bind a value to the question mark.

Because no values are passed, pdo throws an exception (Only tested with where statements):

PDOStatement::execute() [function.PDOStatement-execute]: SQLSTATE[HY093]: Invalid parameter number: no parameters were bound in

Reproduce code:
---------------
<?php

    $db  = new PDO('mysql:host=localhost;dbname=DATABASE', 'USER', 'PASSWORD');
    $sth = $db->prepare("SELECT * FROM `TABLE` WHERE (login = '?\'')");

    $sth->execute();

    var_dump($sth->fetch());

Expected result:
----------------
Array or false

Actual result:
--------------
Exception: PDOStatement::execute() [function.PDOStatement-execute]: SQLSTATE[HY093]: Invalid parameter number: no parameters were bound in

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-09-05 17:59 UTC] tsteiner at nerdclub dot net
This bug is a direct result of the fix for Bug #36798.

The patch for that bug removed code in the parser that would ignore an escaped quote when inside of quotes (ie: "foo\"bar" or 'foo\'bar').

This causes the parser to think it has found the end of quoted text, when it has not.  Because of this, ? characters after an escaped quote are treated as placeholders.  Additionally, I have found it causes the parser to parse beyond the end of the query and into unknown memory contents.

It looks like Bug #36798 needs to be reopened!
 [2008-09-09 14:38 UTC] om at viazenetti dot de
Nice, after almost seven months, this bug still exists and no one cares about it?
 [2008-10-01 17:26 UTC] tsteiner at nerdclub dot net
Here's a patch to PHP 5.2.6 that seems to both fix this bug and not affect the test case in Bug #36798:



--- php-5.2.6/ext/pdo/pdo_sql_parser.re	2007-12-31 01:17:40.000000000 -0600
+++ php-5.2.6.fixed/ext/pdo/pdo_sql_parser.re	2008-09-08 11:06:39.000000000 -0500
@@ -55,8 +55,8 @@
 	*/
 
 	/*!re2c
-		(["] ([^"])* ["])		{ RET(PDO_PARSER_TEXT); }
-		(['] ([^'])* ['])		{ RET(PDO_PARSER_TEXT); }
+		(["](([\\]ANYNOEOF)|ANYNOEOF\["\\])*["]) { RET(PDO_PARSER_TEXT); }
+		(['](([\\]ANYNOEOF)|ANYNOEOF\['\\])*[']) { RET(PDO_PARSER_TEXT); }
 		MULTICHAR{2,}							{ RET(PDO_PARSER_TEXT); }
		BINDCHR						{ RET(PDO_PARSER_BIND); }
 		QUESTION								{ RET(PDO_PARSER_BIND_POS); }
--- php-5.2.6/ext/pdo/pdo_sql_parser.c	2008-04-30 13:37:40.000000000 -0500
+++ php-5.2.6.fixed/ext/pdo/pdo_sql_parser.c	2008-09-08 11:06:43.000000000 -0500
@@ -1,4 +1,5 @@
-/* Generated by re2c 0.11.0 on Mon Nov 26 16:10:28 2007 */
+/* Generated by re2c 0.13.5 on Mon Sep  8 11:06:43 2008 */
+#line 1 "ext/pdo/pdo_sql_parser.re"
 /*
   +----------------------------------------------------------------------+
   | PHP Version 5                                                        |
@@ -17,7 +18,7 @@
   +----------------------------------------------------------------------+
 */
 
-/* $Id: pdo_sql_parser.c,v 1.35.2.6.2.15 2007/12/31 07:20:09 sebastian Exp $ */
+/* $Id: pdo_sql_parser.re,v 1.28.2.4.2.12 2007/12/31 07:17:40 sebastian Exp $ */
 
 #include "php.h"
 #include "php_pdo_driver.h"
@@ -46,15 +47,17 @@
 	char *cursor = s->cur;
 
 	s->tok = cursor;
+	#line 55 "ext/pdo/pdo_sql_parser.re"
 
 
 	
+#line 55 "ext/pdo/pdo_sql_parser.c"
 {
 	YYCTYPE yych;
 
-	if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
 	yych = *YYCURSOR;
-	switch(yych) {
+	switch (yych) {
 	case 0x00:	goto yy11;
 	case '"':	goto yy2;
 	case '\'':	goto yy4;
@@ -63,16 +66,19 @@
 	default:	goto yy8;
 	}
 yy2:
-	yych = *++YYCURSOR;
-	goto yy24;
+	yych = *(YYMARKER = ++YYCURSOR);
+	if (yych >= 0x01) goto yy26;
 yy3:
+#line 63 "ext/pdo/pdo_sql_parser.re"
 	{ SKIP_ONE(PDO_PARSER_TEXT); }
+#line 75 "ext/pdo/pdo_sql_parser.c"
 yy4:
-	yych = *++YYCURSOR;
+	yych = *(YYMARKER = ++YYCURSOR);
+	if (yych <= 0x00) goto yy3;
 	goto yy20;
 yy5:
 	yych = *++YYCURSOR;
-	switch(yych) {
+	switch (yych) {
 	case '0':
 	case '1':
 	case '2':
@@ -142,18 +148,20 @@
 	}
 yy6:
 	++YYCURSOR;
-	switch((yych = *YYCURSOR)) {
+	switch ((yych = *YYCURSOR)) {
 	case ':':
 	case '?':	goto yy13;
 	default:	goto yy7;
 	}
 yy7:
+#line 62 "ext/pdo/pdo_sql_parser.re"
 	{ RET(PDO_PARSER_BIND_POS); }
+#line 160 "ext/pdo/pdo_sql_parser.c"
 yy8:
 	++YYCURSOR;
-	if(YYLIMIT == YYCURSOR) YYFILL(1);
+	if (YYLIMIT <= YYCURSOR) YYFILL(1);
 	yych = *YYCURSOR;
-	switch(yych) {
+	switch (yych) {
 	case 0x00:
 	case '"':
 	case '\'':
@@ -162,26 +170,32 @@
 	default:	goto yy8;
 	}
 yy10:
+#line 64 "ext/pdo/pdo_sql_parser.re"
 	{ RET(PDO_PARSER_TEXT); }
+#line 176 "ext/pdo/pdo_sql_parser.c"
 yy11:
 	++YYCURSOR;
+#line 65 "ext/pdo/pdo_sql_parser.re"
 	{ RET(PDO_PARSER_EOI); }
+#line 181 "ext/pdo/pdo_sql_parser.c"
 yy13:
 	++YYCURSOR;
-	if(YYLIMIT == YYCURSOR) YYFILL(1);
+	if (YYLIMIT <= YYCURSOR) YYFILL(1);
 	yych = *YYCURSOR;
-	switch(yych) {
+	switch (yych) {
 	case ':':
 	case '?':	goto yy13;
 	default:	goto yy15;
 	}
 yy15:
+#line 60 "ext/pdo/pdo_sql_parser.re"
 	{ RET(PDO_PARSER_TEXT); }
+#line 194 "ext/pdo/pdo_sql_parser.c"
 yy16:
 	++YYCURSOR;
-	if(YYLIMIT == YYCURSOR) YYFILL(1);
+	if (YYLIMIT <= YYCURSOR) YYFILL(1);
 	yych = *YYCURSOR;
-	switch(yych) {
+	switch (yych) {
 	case '0':
 	case '1':
 	case '2':
@@ -248,32 +262,58 @@
 	default:	goto yy18;
 	}
 yy18:
+#line 61 "ext/pdo/pdo_sql_parser.re"
 	{ RET(PDO_PARSER_BIND); }
+#line 268 "ext/pdo/pdo_sql_parser.c"
 yy19:
 	++YYCURSOR;
-	if(YYLIMIT == YYCURSOR) YYFILL(1);
+	if (YYLIMIT <= YYCURSOR) YYFILL(1);
 	yych = *YYCURSOR;
 yy20:
-	switch(yych) {
-	case '\'':	goto yy21;
+	switch (yych) {
+	case 0x00:	goto yy21;
+	case '\'':	goto yy23;
+	case '\\':	goto yy22;
 	default:	goto yy19;
 	}
 yy21:
+	YYCURSOR = YYMARKER;
+	goto yy3;
+yy22:
 	++YYCURSOR;
-	{ RET(PDO_PARSER_TEXT); }
+	if (YYLIMIT <= YYCURSOR) YYFILL(1);
+	yych = *YYCURSOR;
+	if (yych <= 0x00) goto yy21;
+	goto yy19;
 yy23:
 	++YYCURSOR;
-	if(YYLIMIT == YYCURSOR) YYFILL(1);
+#line 59 "ext/pdo/pdo_sql_parser.re"
+	{ RET(PDO_PARSER_TEXT); }
+#line 293 "ext/pdo/pdo_sql_parser.c"
+yy25:
+	++YYCURSOR;
+	if (YYLIMIT <= YYCURSOR) YYFILL(1);
 	yych = *YYCURSOR;
-yy24:
-	switch(yych) {
-	case '"':	goto yy25;
-	default:	goto yy23;
+yy26:
+	switch (yych) {
+	case 0x00:	goto yy21;
+	case '"':	goto yy28;
+	case '\\':	goto yy27;
+	default:	goto yy25;
 	}
-yy25:
+yy27:
+	++YYCURSOR;
+	if (YYLIMIT <= YYCURSOR) YYFILL(1);
+	yych = *YYCURSOR;
+	if (yych <= 0x00) goto yy21;
+	goto yy25;
+yy28:
 	++YYCURSOR;
+#line 58 "ext/pdo/pdo_sql_parser.re"
 	{ RET(PDO_PARSER_TEXT); }
+#line 315 "ext/pdo/pdo_sql_parser.c"
 }
+#line 66 "ext/pdo/pdo_sql_parser.re"
 	
 }
 [2008-10-10 12:18 UTC] felipe@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.

Thanks for the patch.

Fixed in 5.2, 5.3 and HEAD.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 14:01:29 2024 UTC