27
27
#include "mysqlnd_debug.h"
28
28
29
29
#define BAIL_IF_NO_MORE_DATA \
30
- if (( size_t)(p - begin) > packet->header.size) { \
30
+ if (UNEXPECTED(( size_t)(p - begin) > packet->header.size) ) { \
31
31
php_error_docref(NULL, E_WARNING, "Premature end of data (mysqlnd_wireprotocol.c:%u)", __LINE__); \
32
32
goto premature_end; \
33
33
} \
@@ -1148,21 +1148,20 @@ void php_mysqlnd_rset_header_free_mem(void * _packet)
1148
1148
}
1149
1149
/* }}} */
1150
1150
1151
- static size_t rset_field_offsets [] =
1152
- {
1153
- STRUCT_OFFSET (MYSQLND_FIELD , catalog ),
1154
- STRUCT_OFFSET (MYSQLND_FIELD , catalog_length ),
1155
- STRUCT_OFFSET (MYSQLND_FIELD , db ),
1156
- STRUCT_OFFSET (MYSQLND_FIELD , db_length ),
1157
- STRUCT_OFFSET (MYSQLND_FIELD , table ),
1158
- STRUCT_OFFSET (MYSQLND_FIELD , table_length ),
1159
- STRUCT_OFFSET (MYSQLND_FIELD , org_table ),
1160
- STRUCT_OFFSET (MYSQLND_FIELD , org_table_length ),
1161
- STRUCT_OFFSET (MYSQLND_FIELD , name ),
1162
- STRUCT_OFFSET (MYSQLND_FIELD , name_length ),
1163
- STRUCT_OFFSET (MYSQLND_FIELD , org_name ),
1164
- STRUCT_OFFSET (MYSQLND_FIELD , org_name_length ),
1165
- };
1151
+ #define READ_RSET_FIELD (field_name ) do { \
1152
+ len = php_mysqlnd_net_field_length(&p); \
1153
+ if (UNEXPECTED(len == MYSQLND_NULL_LENGTH)) { \
1154
+ goto faulty_or_fake; \
1155
+ } else if (len != 0) { \
1156
+ meta->field_name = (const char *)p; \
1157
+ meta->field_name ## _length = len; \
1158
+ p += len; \
1159
+ total_len += len + 1; \
1160
+ } else { \
1161
+ meta->field_name = mysqlnd_empty_string; \
1162
+ meta->field_name ## _length = 0; \
1163
+ } \
1164
+ } while (0)
1166
1165
1167
1166
1168
1167
/* {{{ php_mysqlnd_rset_field_read */
@@ -1183,7 +1182,6 @@ php_mysqlnd_rset_field_read(MYSQLND_CONN_DATA * conn, void * _packet)
1183
1182
char * root_ptr ;
1184
1183
zend_ulong len ;
1185
1184
MYSQLND_FIELD * meta ;
1186
- unsigned int i , field_count = sizeof (rset_field_offsets )/sizeof (size_t );
1187
1185
1188
1186
DBG_ENTER ("php_mysqlnd_rset_field_read" );
1189
1187
@@ -1214,58 +1212,43 @@ php_mysqlnd_rset_field_read(MYSQLND_CONN_DATA * conn, void * _packet)
1214
1212
1215
1213
meta = packet -> metadata ;
1216
1214
1217
- for (i = 0 ; i < field_count ; i += 2 ) {
1218
- len = php_mysqlnd_net_field_length (& p );
1219
- BAIL_IF_NO_MORE_DATA ;
1220
- switch ((len )) {
1221
- case 0 :
1222
- * (const char * * )(((char * )meta ) + rset_field_offsets [i ]) = mysqlnd_empty_string ;
1223
- * (unsigned int * )(((char * )meta ) + rset_field_offsets [i + 1 ]) = 0 ;
1224
- break ;
1225
- case MYSQLND_NULL_LENGTH :
1226
- goto faulty_or_fake ;
1227
- default :
1228
- * (const char * * )(((char * )meta ) + rset_field_offsets [i ]) = (const char * )p ;
1229
- * (unsigned int * )(((char * )meta ) + rset_field_offsets [i + 1 ]) = len ;
1230
- p += len ;
1231
- total_len += len + 1 ;
1232
- break ;
1233
- }
1234
- BAIL_IF_NO_MORE_DATA ;
1235
- }
1215
+ READ_RSET_FIELD (catalog );
1216
+ READ_RSET_FIELD (db );
1217
+ READ_RSET_FIELD (table );
1218
+ READ_RSET_FIELD (org_table );
1219
+ READ_RSET_FIELD (name );
1220
+ READ_RSET_FIELD (org_name );
1236
1221
1237
1222
/* 1 byte length */
1238
- if (12 != * p ) {
1223
+ if (UNEXPECTED ( 12 != * p ) ) {
1239
1224
DBG_ERR_FMT ("Protocol error. Server sent false length. Expected 12 got %d" , (int ) * p );
1240
1225
php_error_docref (NULL , E_WARNING , "Protocol error. Server sent false length. Expected 12" );
1241
1226
}
1242
1227
1228
+ if ((size_t )((p - begin ) + 12 ) > packet -> header .size ) {
1229
+ php_error_docref (NULL , E_WARNING , "Premature end of data (mysqlnd_wireprotocol.c:%u)" , __LINE__ );
1230
+ goto premature_end ;
1231
+ }
1232
+
1243
1233
p ++ ;
1244
- BAIL_IF_NO_MORE_DATA ;
1245
1234
1246
1235
meta -> charsetnr = uint2korr (p );
1247
1236
p += 2 ;
1248
- BAIL_IF_NO_MORE_DATA ;
1249
1237
1250
1238
meta -> length = uint4korr (p );
1251
1239
p += 4 ;
1252
- BAIL_IF_NO_MORE_DATA ;
1253
1240
1254
1241
meta -> type = uint1korr (p );
1255
1242
p += 1 ;
1256
- BAIL_IF_NO_MORE_DATA ;
1257
1243
1258
1244
meta -> flags = uint2korr (p );
1259
1245
p += 2 ;
1260
- BAIL_IF_NO_MORE_DATA ;
1261
1246
1262
1247
meta -> decimals = uint1korr (p );
1263
1248
p += 1 ;
1264
- BAIL_IF_NO_MORE_DATA ;
1265
1249
1266
1250
/* 2 byte filler */
1267
1251
p += 2 ;
1268
- BAIL_IF_NO_MORE_DATA ;
1269
1252
1270
1253
/* Should we set NUM_FLAG (libmysql does it) ? */
1271
1254
if (
@@ -1289,62 +1272,52 @@ php_mysqlnd_rset_field_read(MYSQLND_CONN_DATA * conn, void * _packet)
1289
1272
BAIL_IF_NO_MORE_DATA ;
1290
1273
DBG_INF_FMT ("Def found, length %lu" , len );
1291
1274
meta -> def = packet -> memory_pool -> get_chunk (packet -> memory_pool , len + 1 );
1292
- if (!meta -> def ) {
1293
- SET_OOM_ERROR (error_info );
1294
- DBG_RETURN (FAIL );
1295
- }
1296
1275
memcpy (meta -> def , p , len );
1297
1276
meta -> def [len ] = '\0' ;
1298
1277
meta -> def_length = len ;
1299
1278
p += len ;
1300
1279
}
1301
1280
1302
1281
root_ptr = meta -> root = packet -> memory_pool -> get_chunk (packet -> memory_pool , total_len );
1303
- if (!root_ptr ) {
1304
- SET_OOM_ERROR (error_info );
1305
- DBG_RETURN (FAIL );
1306
- }
1307
-
1308
1282
meta -> root_len = total_len ;
1309
1283
1310
- if (meta -> name != mysqlnd_empty_string ) {
1284
+ if (EXPECTED ( meta -> name_length != 0 ) ) {
1311
1285
meta -> sname = zend_string_init_interned (meta -> name , meta -> name_length , 0 );
1286
+ meta -> name = ZSTR_VAL (meta -> sname );
1312
1287
} else {
1313
1288
meta -> sname = ZSTR_EMPTY_ALLOC ();
1314
1289
}
1315
- meta -> name = ZSTR_VAL (meta -> sname );
1316
- meta -> name_length = ZSTR_LEN (meta -> sname );
1317
1290
1318
1291
/* Now do allocs */
1319
- if (meta -> catalog && meta -> catalog != mysqlnd_empty_string ) {
1292
+ if (meta -> catalog_length != 0 ) {
1320
1293
len = meta -> catalog_length ;
1321
1294
meta -> catalog = memcpy (root_ptr , meta -> catalog , len );
1322
1295
* (root_ptr += len ) = '\0' ;
1323
1296
root_ptr ++ ;
1324
1297
}
1325
1298
1326
- if (meta -> db && meta -> db != mysqlnd_empty_string ) {
1299
+ if (meta -> db_length != 0 ) {
1327
1300
len = meta -> db_length ;
1328
1301
meta -> db = memcpy (root_ptr , meta -> db , len );
1329
1302
* (root_ptr += len ) = '\0' ;
1330
1303
root_ptr ++ ;
1331
1304
}
1332
1305
1333
- if (meta -> table && meta -> table != mysqlnd_empty_string ) {
1306
+ if (meta -> table_length != 0 ) {
1334
1307
len = meta -> table_length ;
1335
1308
meta -> table = memcpy (root_ptr , meta -> table , len );
1336
1309
* (root_ptr += len ) = '\0' ;
1337
1310
root_ptr ++ ;
1338
1311
}
1339
1312
1340
- if (meta -> org_table && meta -> org_table != mysqlnd_empty_string ) {
1313
+ if (meta -> org_table_length != 0 ) {
1341
1314
len = meta -> org_table_length ;
1342
1315
meta -> org_table = memcpy (root_ptr , meta -> org_table , len );
1343
1316
* (root_ptr += len ) = '\0' ;
1344
1317
root_ptr ++ ;
1345
1318
}
1346
1319
1347
- if (meta -> org_name && meta -> org_name != mysqlnd_empty_string ) {
1320
+ if (meta -> org_name_length != 0 ) {
1348
1321
len = meta -> org_name_length ;
1349
1322
meta -> org_name = memcpy (root_ptr , meta -> org_name , len );
1350
1323
* (root_ptr += len ) = '\0' ;
@@ -1385,7 +1358,6 @@ php_mysqlnd_read_row_ex(MYSQLND_PFC * pfc,
1385
1358
enum_func_status ret = PASS ;
1386
1359
MYSQLND_PACKET_HEADER header ;
1387
1360
zend_uchar * p = NULL ;
1388
- zend_bool first_iteration = TRUE;
1389
1361
size_t prealloc_more_bytes ;
1390
1362
1391
1363
DBG_ENTER ("php_mysqlnd_read_row_ex" );
@@ -1405,49 +1377,48 @@ php_mysqlnd_read_row_ex(MYSQLND_PFC * pfc,
1405
1377
prealloc_more_bytes = 1 ;
1406
1378
1407
1379
* data_size = 0 ;
1408
- while (1 ) {
1409
- if (FAIL == mysqlnd_read_header (pfc , vio , & header , stats , error_info )) {
1410
- ret = FAIL ;
1411
- break ;
1412
- }
1413
-
1380
+ if (UNEXPECTED (FAIL == mysqlnd_read_header (pfc , vio , & header , stats , error_info ))) {
1381
+ ret = FAIL ;
1382
+ } else {
1414
1383
* data_size += header .size ;
1384
+ buffer -> ptr = pool -> get_chunk (pool , * data_size + prealloc_more_bytes );
1385
+ p = buffer -> ptr ;
1415
1386
1416
- if (first_iteration ) {
1417
- first_iteration = FALSE;
1418
- buffer -> ptr = pool -> get_chunk (pool , * data_size + prealloc_more_bytes );
1419
- if (!buffer -> ptr ) {
1420
- ret = FAIL ;
1421
- break ;
1422
- }
1423
- p = buffer -> ptr ;
1424
- } else if (!first_iteration ) {
1425
- /* Empty packet after MYSQLND_MAX_PACKET_SIZE packet. That's ok, break */
1426
- if (!header .size ) {
1427
- break ;
1428
- }
1429
-
1430
- /*
1431
- We have to realloc the buffer.
1432
- */
1433
- buffer -> ptr = pool -> resize_chunk (pool , buffer -> ptr , * data_size - header .size , * data_size + prealloc_more_bytes );
1434
- if (!buffer -> ptr ) {
1435
- SET_OOM_ERROR (error_info );
1436
- ret = FAIL ;
1437
- break ;
1438
- }
1439
- /* The position could have changed, recalculate */
1440
- p = (zend_uchar * ) buffer -> ptr + (* data_size - header .size );
1441
- }
1442
-
1443
- if (PASS != (ret = pfc -> data -> m .receive (pfc , vio , p , header .size , stats , error_info ))) {
1387
+ if (UNEXPECTED (PASS != (ret = pfc -> data -> m .receive (pfc , vio , p , header .size , stats , error_info )))) {
1444
1388
DBG_ERR ("Empty row packet body" );
1445
1389
php_error (E_WARNING , "Empty row packet body" );
1446
- break ;
1447
- }
1390
+ } else {
1391
+ while (header .size >= MYSQLND_MAX_PACKET_SIZE ) {
1392
+ if (FAIL == mysqlnd_read_header (pfc , vio , & header , stats , error_info )) {
1393
+ ret = FAIL ;
1394
+ break ;
1395
+ }
1448
1396
1449
- if (header .size < MYSQLND_MAX_PACKET_SIZE ) {
1450
- break ;
1397
+ * data_size += header .size ;
1398
+
1399
+ /* Empty packet after MYSQLND_MAX_PACKET_SIZE packet. That's ok, break */
1400
+ if (!header .size ) {
1401
+ break ;
1402
+ }
1403
+
1404
+ /*
1405
+ We have to realloc the buffer.
1406
+ */
1407
+ buffer -> ptr = pool -> resize_chunk (pool , buffer -> ptr , * data_size - header .size , * data_size + prealloc_more_bytes );
1408
+ if (!buffer -> ptr ) {
1409
+ SET_OOM_ERROR (error_info );
1410
+ ret = FAIL ;
1411
+ break ;
1412
+ }
1413
+ /* The position could have changed, recalculate */
1414
+ p = (zend_uchar * ) buffer -> ptr + (* data_size - header .size );
1415
+
1416
+ if (PASS != (ret = pfc -> data -> m .receive (pfc , vio , p , header .size , stats , error_info ))) {
1417
+ DBG_ERR ("Empty row packet body" );
1418
+ php_error (E_WARNING , "Empty row packet body" );
1419
+ break ;
1420
+ }
1421
+ }
1451
1422
}
1452
1423
}
1453
1424
if (ret == FAIL && buffer -> ptr ) {
0 commit comments