Skip to content

Commit 408042e

Browse files
committed
Improve memory allocation checks
1 parent 1121e5d commit 408042e

File tree

3 files changed

+182
-60
lines changed

3 files changed

+182
-60
lines changed

src/njs/src/njsConnection.cpp

Lines changed: 179 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ Persistent<FunctionTemplate> Connection::connectionTemplate_s;
7373

7474
#define NJS_SIZE_T_MAX std::numeric_limits<std::size_t>::max()
7575

76-
#define NJS_IS_SIZE_T_OVERFLOW(maxSize,maxRows) \
76+
#define NJS_SIZE_T_OVERFLOW(maxSize,maxRows) \
7777
( ( ( maxSize != 0 ) && \
7878
( ( ( NJS_SIZE_T_MAX ) / ( (size_t)maxSize ) ) < (maxRows) ) ) ? 1 : 0) \
7979

@@ -1397,20 +1397,25 @@ void Connection::DoDefines ( eBaton* executeBaton, const dpi::MetaData* meta,
13971397

13981398
defines[col].maxSize = sizeof(double);
13991399

1400-
if ( !NJS_IS_SIZE_T_OVERFLOW ( defines[col].maxSize,
1400+
if ( NJS_SIZE_T_OVERFLOW ( defines[col].maxSize,
14011401
executeBaton->maxRows ) )
14021402
{
1403-
defines[col].buf = (double *)malloc( (size_t)defines[col].maxSize*
1404-
executeBaton->maxRows );
1403+
executeBaton->error = NJSMessages::getErrorMsg( errResultsTooLarge );
1404+
return;
14051405
}
14061406
else
1407-
defines[col].buf = 0;
1408-
1409-
if(!defines[col].buf)
14101407
{
1411-
executeBaton->error = NJSMessages::getErrorMsg(errInsufficientMemory);
1412-
return;
1408+
defines[col].buf = (double *)malloc( (size_t)defines[col].maxSize*
1409+
executeBaton->maxRows );
1410+
1411+
if( !defines[col].buf )
1412+
{
1413+
executeBaton->error = NJSMessages::getErrorMsg(
1414+
errInsufficientMemory );
1415+
return;
1416+
}
14131417
}
1418+
14141419
break;
14151420
case dpi::DpiVarChar :
14161421
case dpi::DpiFixedChar :
@@ -1425,19 +1430,22 @@ void Connection::DoDefines ( eBaton* executeBaton, const dpi::MetaData* meta,
14251430

14261431
defines[col].maxSize = (meta[col].dbSize) * NJS_CHAR_CONVERSION_RATIO;
14271432

1428-
if ( !NJS_IS_SIZE_T_OVERFLOW ( defines[col].maxSize,
1433+
if ( NJS_SIZE_T_OVERFLOW ( defines[col].maxSize,
14291434
executeBaton->maxRows ) )
14301435
{
1431-
defines[col].buf = (char *)malloc( (size_t)defines[col].maxSize*
1432-
executeBaton->maxRows );
1436+
executeBaton->error = NJSMessages::getErrorMsg( errResultsTooLarge );
1437+
return;
14331438
}
14341439
else
1435-
defines[col].buf = 0;
1436-
1437-
if(!defines[col].buf)
14381440
{
1439-
executeBaton->error = NJSMessages::getErrorMsg(errInsufficientMemory);
1440-
return;
1441+
defines[col].buf = (char *)malloc( (size_t)defines[col].maxSize*
1442+
executeBaton->maxRows );
1443+
if( !defines[col].buf )
1444+
{
1445+
executeBaton->error = NJSMessages::getErrorMsg(
1446+
errInsufficientMemory );
1447+
return;
1448+
}
14411449
}
14421450
break;
14431451
case dpi::DpiDate :
@@ -1473,21 +1481,25 @@ void Connection::DoDefines ( eBaton* executeBaton, const dpi::MetaData* meta,
14731481
/* Fetching DATE/TIMESTAMP values as VARCHAR */
14741482
defines[col].maxSize = NJS_MAX_FETCH_AS_STRING_SIZE ;
14751483

1476-
if ( !NJS_IS_SIZE_T_OVERFLOW ( defines[col].maxSize,
1484+
if ( NJS_SIZE_T_OVERFLOW ( defines[col].maxSize,
14771485
executeBaton->maxRows ) )
14781486
{
1479-
defines[col].buf = (char *)malloc( (size_t)defines[col].maxSize*
1480-
executeBaton->maxRows );
1487+
executeBaton->error = NJSMessages::getErrorMsg( errResultsTooLarge );
1488+
return;
14811489
}
14821490
else
1483-
defines[col].buf = 0;
1484-
1485-
if(!defines[col].buf)
14861491
{
1487-
executeBaton->error = NJSMessages::getErrorMsg(
1488-
errInsufficientMemory);
1489-
return;
1492+
defines[col].buf = (char *)malloc( (size_t)defines[col].maxSize*
1493+
executeBaton->maxRows );
1494+
1495+
if( !defines[col].buf )
1496+
{
1497+
executeBaton->error = NJSMessages::getErrorMsg(
1498+
errInsufficientMemory);
1499+
return;
1500+
}
14901501
}
1502+
14911503
}
14921504
break;
14931505

@@ -1497,19 +1509,22 @@ void Connection::DoDefines ( eBaton* executeBaton, const dpi::MetaData* meta,
14971509
defines[col].fetchType = meta[col].dbType;
14981510
defines[col].maxSize = sizeof(Descriptor *);
14991511

1500-
if ( !NJS_IS_SIZE_T_OVERFLOW ( defines[col].maxSize,
1512+
if ( NJS_SIZE_T_OVERFLOW ( defines[col].maxSize,
15011513
executeBaton->maxRows ) )
15021514
{
1503-
defines[col].buf = malloc( (size_t)defines[col].maxSize*
1504-
executeBaton->maxRows );
1515+
executeBaton->error = NJSMessages::getErrorMsg( errResultsTooLarge );
1516+
return;
15051517
}
15061518
else
1507-
defines[col].buf = 0;
1508-
1509-
if(!defines[col].buf)
15101519
{
1511-
executeBaton->error = NJSMessages::getErrorMsg(errInsufficientMemory);
1512-
return;
1520+
defines[col].buf = malloc( (size_t)defines[col].maxSize*
1521+
executeBaton->maxRows );
1522+
1523+
if( !defines[col].buf )
1524+
{
1525+
executeBaton->error = NJSMessages::getErrorMsg( errInsufficientMemory );
1526+
return;
1527+
}
15131528
}
15141529

15151530
for (unsigned int j = 0; j < executeBaton->maxRows; j++)
@@ -1531,20 +1546,23 @@ void Connection::DoDefines ( eBaton* executeBaton, const dpi::MetaData* meta,
15311546
}
15321547
defines[col].maxSize = NJS_MAX_FETCH_AS_STRING_SIZE;
15331548

1534-
if ( !NJS_IS_SIZE_T_OVERFLOW ( defines[col].maxSize,
1549+
if ( NJS_SIZE_T_OVERFLOW ( defines[col].maxSize,
15351550
executeBaton->maxRows ) )
15361551
{
1537-
defines[col].buf = (char *)malloc( (size_t)defines[col].maxSize*
1538-
executeBaton->maxRows );
1552+
executeBaton->error = NJSMessages::getErrorMsg( errResultsTooLarge );
1553+
return;
15391554
}
15401555
else
1541-
defines[col].buf = 0;
1542-
1543-
if(!defines[col].buf)
15441556
{
1545-
executeBaton->error = NJSMessages::getErrorMsg(
1546-
errInsufficientMemory);
1547-
return;
1557+
defines[col].buf = (char *)malloc( (size_t)defines[col].maxSize*
1558+
executeBaton->maxRows );
1559+
1560+
if( !defines[col].buf )
1561+
{
1562+
executeBaton->error = NJSMessages::getErrorMsg(
1563+
errInsufficientMemory);
1564+
return;
1565+
}
15481566
}
15491567
break;
15501568

@@ -1557,14 +1575,14 @@ void Connection::DoDefines ( eBaton* executeBaton, const dpi::MetaData* meta,
15571575
defines[col].ind = (short*)malloc (sizeof(short)*(executeBaton->maxRows));
15581576
if(!defines[col].ind)
15591577
{
1560-
executeBaton->error = NJSMessages::getErrorMsg(errInsufficientMemory);
1578+
executeBaton->error = NJSMessages::getErrorMsg( errInsufficientMemory );
15611579
return;
15621580
}
15631581
defines[col].len = (DPI_BUFLEN_TYPE *)malloc(sizeof(DPI_BUFLEN_TYPE)*
15641582
executeBaton->maxRows);
15651583
if(!defines[col].len)
15661584
{
1567-
executeBaton->error = NJSMessages::getErrorMsg(errInsufficientMemory);
1585+
executeBaton->error = NJSMessages::getErrorMsg( errInsufficientMemory );
15681586
return;
15691587
}
15701588

@@ -2799,10 +2817,36 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
27992817
eBaton *executeBaton = (eBaton *)ctx;
28002818
Bind *bind = (Bind *)executeBaton->binds[bndpos];
28012819

2802-
bind->ind = (short *)malloc ( nRows * sizeof ( short ) ) ;
2820+
if ( NJS_SIZE_T_OVERFLOW ( nRows, sizeof ( short )))
2821+
{
2822+
executeBaton->error = NJSMessages::getErrorMsg( errResultsTooLarge );
2823+
return;
2824+
}
2825+
else
2826+
{
2827+
bind->ind = (short *)malloc ( nRows * sizeof ( short ) ) ;
2828+
if( !bind->ind )
2829+
{
2830+
executeBaton->error = NJSMessages::getErrorMsg( errInsufficientMemory );
2831+
return;
2832+
}
2833+
}
28032834
if ( dmlReturning )
28042835
{
2805-
bind->len2 = ( unsigned int *)malloc ( nRows * sizeof ( unsigned int ) );
2836+
if ( NJS_SIZE_T_OVERFLOW ( nRows, sizeof ( unsigned int )))
2837+
{
2838+
executeBaton->error = NJSMessages::getErrorMsg( errResultsTooLarge );
2839+
return;
2840+
}
2841+
else
2842+
{
2843+
bind->len2 = ( unsigned int *)malloc ( nRows * sizeof ( unsigned int ) );
2844+
if( !bind->len2 )
2845+
{
2846+
executeBaton->error = NJSMessages::getErrorMsg( errInsufficientMemory );
2847+
return;
2848+
}
2849+
}
28062850
}
28072851
else
28082852
{
@@ -2815,18 +2859,20 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
28152859
case dpi::DpiVarChar:
28162860
/* one extra char for EOS */
28172861

2818-
if ( !NJS_IS_SIZE_T_OVERFLOW ( (bind->maxSize + 1), nRows) )
2862+
if ( NJS_SIZE_T_OVERFLOW ( (bind->maxSize + 1), nRows) )
28192863
{
2820-
bind->value = (char *)malloc( (size_t)( bind->maxSize + 1) * nRows );
2864+
executeBaton->error = NJSMessages::getErrorMsg( errResultsTooLarge );
2865+
return;
28212866
}
28222867
else
2823-
bind->value = 0;
2824-
2825-
if( !bind->value )
28262868
{
2827-
executeBaton->error = NJSMessages::getErrorMsg(
2828-
errInsufficientMemory);
2829-
return;
2869+
bind->value = (char *)malloc( (size_t)( bind->maxSize + 1) * nRows );
2870+
if( !bind->value )
2871+
{
2872+
executeBaton->error = NJSMessages::getErrorMsg(
2873+
errInsufficientMemory);
2874+
return;
2875+
}
28302876
}
28312877

28322878
if ( dmlReturning )
@@ -2840,23 +2886,69 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
28402886
break;
28412887

28422888
case dpi::DpiInteger:
2843-
bind->value = ( int *) malloc ( sizeof (int) * nRows ) ;
2889+
if ( NJS_SIZE_T_OVERFLOW ( sizeof (int), nRows) )
2890+
{
2891+
executeBaton->error = NJSMessages::getErrorMsg( errResultsTooLarge );
2892+
return;
2893+
}
2894+
else
2895+
{
2896+
bind->value = ( int *) malloc ( sizeof (int) * nRows ) ;
2897+
if( !bind->value )
2898+
{
2899+
executeBaton->error = NJSMessages::getErrorMsg(
2900+
errInsufficientMemory);
2901+
return;
2902+
}
2903+
}
28442904
if ( !dmlReturning )
28452905
{
28462906
*(bind->len) = sizeof ( int ) ;
28472907
}
28482908
break;
28492909

28502910
case dpi::DpiUnsignedInteger:
2851-
bind->value = ( unsigned int *)malloc ( sizeof ( unsigned int ) * nRows );
2911+
if ( NJS_SIZE_T_OVERFLOW ( sizeof ( unsigned int ), nRows) )
2912+
{
2913+
executeBaton->error = NJSMessages::getErrorMsg( errResultsTooLarge );
2914+
return;
2915+
}
2916+
else
2917+
{
2918+
bind->value = ( unsigned int *)malloc ( sizeof ( unsigned int ) * nRows );
2919+
if( !bind->value )
2920+
{
2921+
executeBaton->error = NJSMessages::getErrorMsg(
2922+
errInsufficientMemory);
2923+
return;
2924+
}
2925+
}
28522926
if ( !dmlReturning )
28532927
{
28542928
*(bind->len) = sizeof ( unsigned int ) ;
28552929
}
28562930
break;
28572931

28582932
case dpi::DpiDouble:
2859-
bind->value = ( double *)malloc ( sizeof ( double ) * nRows );
2933+
if ( NJS_SIZE_T_OVERFLOW ( sizeof ( double ), nRows) )
2934+
{
2935+
executeBaton->error = NJSMessages::getErrorMsg( errResultsTooLarge );
2936+
return;
2937+
}
2938+
else
2939+
{
2940+
bind->value = ( double *)malloc ( sizeof ( double ) * nRows );
2941+
if( !bind->value )
2942+
{
2943+
executeBaton->error = NJSMessages::getErrorMsg(
2944+
errInsufficientMemory);
2945+
return;
2946+
}
2947+
}
2948+
if ( !dmlReturning )
2949+
{
2950+
*(bind->len) = sizeof ( unsigned int ) ;
2951+
}
28602952
if ( !dmlReturning )
28612953
{
28622954
*(bind->len) = sizeof ( double ) ;
@@ -2872,7 +2964,21 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
28722964
if (nRows > 1)
28732965
bind->rowsReturned = nRows;
28742966
// allocate the array of Descriptor **
2875-
bind->value = (void *)malloc(sizeof(Descriptor *) * bind->rowsReturned);
2967+
if ( NJS_SIZE_T_OVERFLOW ( sizeof ( Descriptor * ), nRows) )
2968+
{
2969+
executeBaton->error = NJSMessages::getErrorMsg( errResultsTooLarge );
2970+
return;
2971+
}
2972+
else
2973+
{
2974+
bind->value = (void *)malloc(sizeof(Descriptor *) * bind->rowsReturned);
2975+
if( !bind->value )
2976+
{
2977+
executeBaton->error = NJSMessages::getErrorMsg(
2978+
errInsufficientMemory);
2979+
return;
2980+
}
2981+
}
28762982
// and allocate the underlying descriptor(s)
28772983
for (unsigned int rowsidx = 0; rowsidx < bind->rowsReturned; rowsidx++)
28782984
{
@@ -2887,8 +2993,22 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
28872993
break;
28882994

28892995
case dpi::DpiTimestampLTZ:
2996+
{
2997+
if ( NJS_SIZE_T_OVERFLOW ( sizeof ( long double ), nRows) )
2998+
{
2999+
executeBaton->error = NJSMessages::getErrorMsg( errResultsTooLarge );
3000+
return;
3001+
}
3002+
else
28903003
{
28913004
bind->extvalue = (long double *) malloc ( sizeof ( long double ) * nRows );
3005+
if( !bind->extvalue )
3006+
{
3007+
executeBaton->error = NJSMessages::getErrorMsg(
3008+
errInsufficientMemory);
3009+
return;
3010+
}
3011+
}
28923012
// needed to post-process DML RETURNING of TimestampLTZ
28933013
// rowsReturns for INSERT will be zero,
28943014
// but we still need to allocate one descriptor

src/njs/src/njsMessages.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ static const char *errMsg[] =
5858
"NJS-021: invalid type for conversion specified",
5959
"NJS-022: invalid LOB",
6060
"NJS-023: concurrent operations on LOB are not allowed",
61-
"NJS-024: memory allocation failed",
61+
"NJS-024: memory allocation failed",
62+
"NJS-025: results area too large to allocate memory"
6263
};
6364

6465
string NJSMessages::getErrorMsg ( NJSErrorType err, ... )

src/njs/src/njsMessages.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ typedef enum
5858
errInvalidLob,
5959
errBusyLob,
6060
errInsufficientMemory,
61+
errResultsTooLarge,
6162

6263
// New ones should be added here
6364

0 commit comments

Comments
 (0)