In the built-in SQL function implementations, improve some comments, fix
an off-by-one error in detecting over-size strings, and add testcase() macros to verify that boundary values have been tested. (CVS 6434) FossilOrigin-Name: 868a487f5fd7c795e04a08de36a85ba1e06bc8c6
This commit is contained in:
+21
-8
@@ -16,7 +16,7 @@
|
||||
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
||||
** All other code has file scope.
|
||||
**
|
||||
** $Id: func.c,v 1.227 2009/04/02 09:07:13 drh Exp $
|
||||
** $Id: func.c,v 1.228 2009/04/02 10:16:18 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <stdlib.h>
|
||||
@@ -266,12 +266,17 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
/*
|
||||
** Allocate nByte bytes of space using sqlite3_malloc(). If the
|
||||
** allocation fails, call sqlite3_result_error_nomem() to notify
|
||||
** the database handle that malloc() has failed.
|
||||
** the database handle that malloc() has failed and return NULL.
|
||||
** If nByte is larger than the maximum string or blob length, then
|
||||
** raise an SQLITE_TOOBIG exception and return NULL.
|
||||
*/
|
||||
static void *contextMalloc(sqlite3_context *context, i64 nByte){
|
||||
char *z;
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
assert( nByte>0 );
|
||||
if( nByte>sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH] );
|
||||
testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
|
||||
if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
sqlite3_result_error_toobig(context);
|
||||
z = 0;
|
||||
}else{
|
||||
@@ -624,6 +629,7 @@ static void likeFunc(
|
||||
){
|
||||
const unsigned char *zA, *zB;
|
||||
int escape = 0;
|
||||
int nPat;
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
|
||||
zB = sqlite3_value_text(argv[0]);
|
||||
@@ -632,8 +638,10 @@ static void likeFunc(
|
||||
/* Limit the length of the LIKE or GLOB pattern to avoid problems
|
||||
** of deep recursion and N*N behavior in patternCompare().
|
||||
*/
|
||||
if( sqlite3_value_bytes(argv[0]) >
|
||||
db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ){
|
||||
nPat = sqlite3_value_bytes(argv[0]);
|
||||
testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] );
|
||||
testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]+1 );
|
||||
if( nPat > db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ){
|
||||
sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1);
|
||||
return;
|
||||
}
|
||||
@@ -809,10 +817,13 @@ static void zeroblobFunc(
|
||||
sqlite3_value **argv
|
||||
){
|
||||
i64 n;
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
assert( argc==1 );
|
||||
UNUSED_PARAMETER(argc);
|
||||
n = sqlite3_value_int64(argv[0]);
|
||||
if( n>sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH] );
|
||||
testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
|
||||
if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
sqlite3_result_error_toobig(context);
|
||||
}else{
|
||||
sqlite3_result_zeroblob(context, (int)n);
|
||||
@@ -878,7 +889,9 @@ static void replaceFunc(
|
||||
u8 *zOld;
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
nOut += nRep - nPattern;
|
||||
if( nOut>=db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] );
|
||||
testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] );
|
||||
if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
sqlite3_result_error_toobig(context);
|
||||
sqlite3DbFree(db, zOut);
|
||||
return;
|
||||
@@ -962,7 +975,7 @@ static void trimFunc(
|
||||
int len = 0;
|
||||
for(i=0; i<nChar; i++){
|
||||
len = aLen[i];
|
||||
if( memcmp(zIn, azChar[i], len)==0 ) break;
|
||||
if( len<=nIn && memcmp(zIn, azChar[i], len)==0 ) break;
|
||||
}
|
||||
if( i>=nChar ) break;
|
||||
zIn += len;
|
||||
|
||||
Reference in New Issue
Block a user