@@ -293,7 +293,7 @@ static FbTokenType getToken(const char** begin, const char* end)
293293 return ret ;
294294}
295295
296- int preprocess (const zend_string * sql , char * sql_out , HashTable * named_params )
296+ int preprocess (const zend_string * sql , char * sql_out , size_t * sql_out_len , HashTable * named_params )
297297{
298298 bool passAsIs = 1 , execBlock = 0 ;
299299 zend_long pindex = -1 ;
@@ -324,7 +324,7 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
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 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
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 = 0 ;
@@ -365,22 +365,28 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
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 = getToken (& p , end );
378382 switch (tok )
379383 {
380- case ttParamMark :
381- tok = getToken (& p , end );
384+ case ttParamMark : {
385+ const char * p_peek = p ;
386+ tok = getToken (& 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 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
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 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
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 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
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 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
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 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
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 :
@@ -456,6 +467,8 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
456467 break ;
457468 }
458469 }
470+ * sql_out_p = '\0' ;
471+ * sql_out_len = sql_out_p - sql_out ;
459472 return 1 ;
460473}
461474
@@ -665,7 +678,7 @@ static zend_long firebird_handle_doer(pdo_dbh_t *dbh, const zend_string *sql) /*
665678static zend_string * firebird_handle_quoter (pdo_dbh_t * dbh , const zend_string * unquoted , enum pdo_param_type paramtype )
666679{
667680 size_t qcount = 0 ;
668- char const * co , * l , * r ;
681+ char const * co , * l ;
669682 char * c ;
670683 size_t quotedlen ;
671684 zend_string * quoted_str ;
@@ -674,9 +687,15 @@ static zend_string* firebird_handle_quoter(pdo_dbh_t *dbh, const zend_string *un
674687 return ZSTR_INIT_LITERAL ("''" , 0 );
675688 }
676689
690+ const char * const end = ZSTR_VAL (unquoted ) + ZSTR_LEN (unquoted );
691+
677692 /* Firebird only requires single quotes to be doubled if string lengths are used */
678693 /* count the number of ' characters */
679- for (co = ZSTR_VAL (unquoted ); (co = strchr (co ,'\'' )); qcount ++ , co ++ );
694+ for (co = ZSTR_VAL (unquoted ); co < end ; co ++ ) {
695+ if (* co == '\'' ) {
696+ qcount ++ ;
697+ }
698+ }
680699
681700 if (UNEXPECTED (ZSTR_LEN (unquoted ) + 2 > ZSTR_MAX_LEN - qcount )) {
682701 return NULL ;
@@ -688,15 +707,14 @@ static zend_string* firebird_handle_quoter(pdo_dbh_t *dbh, const zend_string *un
688707 * c ++ = '\'' ;
689708
690709 /* foreach (chunk that ends in a quote) */
691- for (l = ZSTR_VAL (unquoted ); (r = strchr (l ,'\'' )); l = r + 1 ) {
692- strncpy (c , l , r - l + 1 );
693- c += (r - l + 1 );
694- /* add the second quote */
695- * c ++ = '\'' ;
710+ for (l = ZSTR_VAL (unquoted ); l < end ; l ++ ) {
711+ * c ++ = * l ;
712+ if (* l == '\'' ) {
713+ /* add the second quote */
714+ * c ++ = '\'' ;
715+ }
696716 }
697717
698- /* copy the remainder */
699- strncpy (c , l , quotedlen - (c - ZSTR_VAL (quoted_str ))- 1 );
700718 ZSTR_VAL (quoted_str )[quotedlen - 1 ] = '\'' ;
701719 ZSTR_VAL (quoted_str )[quotedlen ] = '\0' ;
702720
@@ -789,6 +807,7 @@ static int firebird_alloc_prepare_stmt(pdo_dbh_t *dbh, const zend_string *sql,
789807{
790808 pdo_firebird_db_handle * H = (pdo_firebird_db_handle * )dbh -> driver_data ;
791809 char * new_sql ;
810+ size_t new_sql_len ;
792811
793812 /* Firebird allows SQL statements up to 64k, so bail if it doesn't fit */
794813 if (ZSTR_LEN (sql ) > 65536 ) {
@@ -816,14 +835,14 @@ static int firebird_alloc_prepare_stmt(pdo_dbh_t *dbh, const zend_string *sql,
816835 we need to replace :foo by ?, and store the name we just replaced */
817836 new_sql = emalloc (ZSTR_LEN (sql )+ 1 );
818837 new_sql [0 ] = '\0' ;
819- if (!preprocess (sql , new_sql , named_params )) {
838+ if (!preprocess (sql , new_sql , & new_sql_len , named_params )) {
820839 strcpy (dbh -> error_code , "07000" );
821840 efree (new_sql );
822841 return 0 ;
823842 }
824843
825844 /* prepare the statement */
826- if (isc_dsql_prepare (H -> isc_status , & H -> tr , s , 0 , new_sql , H -> sql_dialect , out_sqlda )) {
845+ if (isc_dsql_prepare (H -> isc_status , & H -> tr , s , new_sql_len , new_sql , H -> sql_dialect , out_sqlda )) {
827846 RECORD_ERROR (dbh );
828847 efree (new_sql );
829848 return 0 ;
0 commit comments