@@ -293,7 +293,7 @@ static FbTokenType php_firebird_get_token(const char** begin, const char* end)
293293 return ret ;
294294}
295295
296- static int php_firebird_preprocess (const zend_string * sql , char * sql_out , HashTable * named_params )
296+ static int php_firebird_preprocess (const zend_string * sql , char * sql_out , size_t * sql_out_len , HashTable * named_params )
297297{
298298 bool passAsIs = true, execBlock = false;
299299 zend_long pindex = -1 ;
@@ -324,7 +324,7 @@ static int php_firebird_preprocess(const zend_string* sql, char* sql_out, HashTa
324324 if (l > 252 ) {
325325 return 0 ;
326326 }
327- strncpy (ident , i , l );
327+ memcpy (ident , i , l );
328328 ident [l ] = '\0' ;
329329 if (!strcasecmp (ident , "EXECUTE" ))
330330 {
@@ -349,7 +349,7 @@ static int php_firebird_preprocess(const zend_string* sql, char* sql_out, HashTa
349349 if (l > 252 ) {
350350 return 0 ;
351351 }
352- strncpy (ident2 , i2 , l );
352+ memcpy (ident2 , i2 , l );
353353 ident2 [l ] = '\0' ;
354354 execBlock = !strcasecmp (ident2 , "BLOCK" );
355355 passAsIs = false;
@@ -365,22 +365,28 @@ static int php_firebird_preprocess(const zend_string* sql, char* sql_out, HashTa
365365
366366 if (passAsIs )
367367 {
368- strcpy (sql_out , ZSTR_VAL (sql ));
368+ memcpy (sql_out , ZSTR_VAL (sql ), ZSTR_LEN (sql ));
369+ sql_out [ZSTR_LEN (sql )] = '\0' ;
370+ * sql_out_len = ZSTR_LEN (sql );
369371 return 1 ;
370372 }
371373
372- strncat (sql_out , start , p - start );
374+ char * sql_out_p = sql_out ;
375+ memcpy (sql_out_p , start , p - start );
376+ sql_out_p += p - start ;
373377
374378 while (p < end )
375379 {
376380 start = p ;
377381 tok = php_firebird_get_token (& p , end );
378382 switch (tok )
379383 {
380- case ttParamMark :
381- tok = php_firebird_get_token (& p , end );
384+ case ttParamMark : {
385+ const char * p_peek = p ;
386+ tok = php_firebird_get_token (& p_peek , end );
382387 if (tok == ttIdent /*|| tok == ttString*/ )
383388 {
389+ p = p_peek ;
384390 ++ pindex ;
385391 l = p - start ;
386392 /* check the length of the identifier */
@@ -389,7 +395,7 @@ static int php_firebird_preprocess(const zend_string* sql, char* sql_out, HashTa
389395 if (l > 253 ) {
390396 return 0 ;
391397 }
392- strncpy (pname , start , l );
398+ memcpy (pname , start , l );
393399 pname [l ] = '\0' ;
394400
395401 if (named_params ) {
@@ -398,7 +404,7 @@ static int php_firebird_preprocess(const zend_string* sql, char* sql_out, HashTa
398404 zend_hash_str_update (named_params , pname , l , & tmp );
399405 }
400406
401- strcat ( sql_out , "?" ) ;
407+ * sql_out_p ++ = '?' ;
402408 }
403409 else
404410 {
@@ -408,10 +414,11 @@ static int php_firebird_preprocess(const zend_string* sql, char* sql_out, HashTa
408414 return 0 ;
409415 }
410416 ++ pindex ;
411- strncat (sql_out , start , p - start );
417+ memcpy (sql_out_p , start , p - start );
418+ sql_out_p += p - start ;
412419 }
413420 break ;
414-
421+ }
415422 case ttIdent :
416423 if (execBlock )
417424 {
@@ -423,11 +430,14 @@ static int php_firebird_preprocess(const zend_string* sql, char* sql_out, HashTa
423430 if (l > 252 ) {
424431 return 0 ;
425432 }
426- strncpy (ident , start , l );
433+ memcpy (ident , start , l );
427434 ident [l ] = '\0' ;
428435 if (!strcasecmp (ident , "AS" ))
429436 {
430- strncat (sql_out , start , end - start );
437+ memcpy (sql_out_p , start , end - start );
438+ sql_out_p += end - start ;
439+ * sql_out_p = '\0' ;
440+ * sql_out_len = sql_out_p - sql_out ;
431441 return 1 ;
432442 }
433443 }
@@ -438,7 +448,8 @@ static int php_firebird_preprocess(const zend_string* sql, char* sql_out, HashTa
438448 case ttComment :
439449 case ttString :
440450 case ttOther :
441- strncat (sql_out , start , p - start );
451+ memcpy (sql_out_p , start , p - start );
452+ sql_out_p += p - start ;
442453 break ;
443454
444455 case ttBrokenComment :
@@ -455,6 +466,8 @@ static int php_firebird_preprocess(const zend_string* sql, char* sql_out, HashTa
455466 return 0 ;
456467 }
457468 }
469+ * sql_out_p = '\0' ;
470+ * sql_out_len = sql_out_p - sql_out ;
458471 return 1 ;
459472}
460473
@@ -789,7 +802,7 @@ static zend_long firebird_handle_doer(pdo_dbh_t *dbh, const zend_string *sql) /*
789802static zend_string * firebird_handle_quoter (pdo_dbh_t * dbh , const zend_string * unquoted , enum pdo_param_type paramtype )
790803{
791804 size_t qcount = 0 ;
792- char const * co , * l , * r ;
805+ char const * co , * l ;
793806 char * c ;
794807 size_t quotedlen ;
795808 zend_string * quoted_str ;
@@ -798,9 +811,15 @@ static zend_string* firebird_handle_quoter(pdo_dbh_t *dbh, const zend_string *un
798811 return ZSTR_INIT_LITERAL ("''" , 0 );
799812 }
800813
814+ const char * const end = ZSTR_VAL (unquoted ) + ZSTR_LEN (unquoted );
815+
801816 /* Firebird only requires single quotes to be doubled if string lengths are used */
802817 /* count the number of ' characters */
803- for (co = ZSTR_VAL (unquoted ); (co = strchr (co ,'\'' )); qcount ++ , co ++ );
818+ for (co = ZSTR_VAL (unquoted ); co < end ; co ++ ) {
819+ if (* co == '\'' ) {
820+ qcount ++ ;
821+ }
822+ }
804823
805824 if (UNEXPECTED (ZSTR_LEN (unquoted ) + 2 > ZSTR_MAX_LEN - qcount )) {
806825 return NULL ;
@@ -812,15 +831,14 @@ static zend_string* firebird_handle_quoter(pdo_dbh_t *dbh, const zend_string *un
812831 * c ++ = '\'' ;
813832
814833 /* foreach (chunk that ends in a quote) */
815- for (l = ZSTR_VAL (unquoted ); (r = strchr (l ,'\'' )); l = r + 1 ) {
816- strncpy (c , l , r - l + 1 );
817- c += (r - l + 1 );
818- /* add the second quote */
819- * c ++ = '\'' ;
834+ for (l = ZSTR_VAL (unquoted ); l < end ; l ++ ) {
835+ * c ++ = * l ;
836+ if (* l == '\'' ) {
837+ /* add the second quote */
838+ * c ++ = '\'' ;
839+ }
820840 }
821841
822- /* copy the remainder */
823- strncpy (c , l , quotedlen - (c - ZSTR_VAL (quoted_str ))- 1 );
824842 ZSTR_VAL (quoted_str )[quotedlen - 1 ] = '\'' ;
825843 ZSTR_VAL (quoted_str )[quotedlen ] = '\0' ;
826844
@@ -998,6 +1016,7 @@ static int php_firebird_alloc_prepare_stmt(pdo_dbh_t *dbh, const zend_string *sq
9981016{
9991017 pdo_firebird_db_handle * H = (pdo_firebird_db_handle * )dbh -> driver_data ;
10001018 char * new_sql ;
1019+ size_t new_sql_len ;
10011020
10021021 /* allocate the statement */
10031022 if (isc_dsql_allocate_statement (H -> isc_status , & H -> db , s )) {
@@ -1009,14 +1028,14 @@ static int php_firebird_alloc_prepare_stmt(pdo_dbh_t *dbh, const zend_string *sq
10091028 we need to replace :foo by ?, and store the name we just replaced */
10101029 new_sql = emalloc (ZSTR_LEN (sql )+ 1 );
10111030 new_sql [0 ] = '\0' ;
1012- if (!php_firebird_preprocess (sql , new_sql , named_params )) {
1031+ if (!php_firebird_preprocess (sql , new_sql , & new_sql_len , named_params )) {
10131032 php_firebird_error_with_info (dbh , "07000" , strlen ("07000" ), NULL , 0 );
10141033 efree (new_sql );
10151034 return 0 ;
10161035 }
10171036
10181037 /* prepare the statement */
1019- if (isc_dsql_prepare (H -> isc_status , & H -> tr , s , 0 , new_sql , H -> sql_dialect , out_sqlda )) {
1038+ if (isc_dsql_prepare (H -> isc_status , & H -> tr , s , new_sql_len , new_sql , H -> sql_dialect , out_sqlda )) {
10201039 php_firebird_error (dbh );
10211040 efree (new_sql );
10221041 return 0 ;
0 commit comments