Index: src/func.c ================================================================== --- src/func.c +++ src/func.c @@ -14,11 +14,11 @@ ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: func.c,v 1.159 2007/05/15 14:40:11 drh Exp $ +** $Id: func.c,v 1.160 2007/06/07 19:08:33 drh Exp $ */ #include "sqliteInt.h" #include /* #include */ #include @@ -754,14 +754,18 @@ static void zeroblobFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ - int n; + i64 n; assert( argc==1 ); - n = sqlite3_value_int(argv[0]); - sqlite3_result_zeroblob(context, n); + n = sqlite3_value_int64(argv[0]); + if( n>SQLITE_MAX_LENGTH ){ + sqlite3_result_error_toobig(context); + }else{ + sqlite3_result_zeroblob(context, n); + } } /* ** The replace() function. Three arguments are all strings: call ** them A, B, and C. The result is also a string which is derived Index: src/limits.h ================================================================== --- src/limits.h +++ src/limits.h @@ -10,11 +10,11 @@ ** ************************************************************************* ** ** This file defines various limits of what SQLite can process. ** -** @(#) $Id: limits.h,v 1.7 2007/06/07 10:55:36 drh Exp $ +** @(#) $Id: limits.h,v 1.8 2007/06/07 19:08:34 drh Exp $ */ /* ** The maximum length of a TEXT or BLOB in bytes. This also ** limits the size of a row in a table or index. @@ -78,10 +78,11 @@ # define SQLITE_MAX_COMPOUND_SELECT 100 #endif /* ** The maximum number of opcodes in a VDBE program. +** Not currently enforced. */ #ifndef SQLITE_MAX_VDBE_OP # define SQLITE_MAX_VDBE_OP 25000 #endif Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -41,11 +41,11 @@ ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.623 2007/05/23 06:31:39 drh Exp $ +** $Id: vdbe.c,v 1.624 2007/06/07 19:08:34 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include #include @@ -5137,12 +5137,11 @@ too_big: sqlite3SetString(&p->zErrMsg, "string or blob too big", (char*)0); rc = SQLITE_TOOBIG; goto vdbe_halt; - /* Jump to here if a malloc() fails. It's hard to get a malloc() - ** to fail on a modern VM computer, so this code is untested. + /* Jump to here if a malloc() fails. */ no_mem: sqlite3SetString(&p->zErrMsg, "out of memory", (char*)0); rc = SQLITE_NOMEM; goto vdbe_halt; Index: src/vdbemem.c ================================================================== --- src/vdbemem.c +++ src/vdbemem.c @@ -96,12 +96,15 @@ */ #ifndef SQLITE_OMIT_INCRBLOB int sqlite3VdbeMemExpandBlob(Mem *pMem){ if( pMem->flags & MEM_Zero ){ char *pNew; + int nByte; assert( (pMem->flags & MEM_Blob)!=0 ); - pNew = sqliteMalloc(pMem->n+pMem->u.i); + nByte = pMem->n + pMem->u.i; + if( nByte<=0 ) nByte = 1; + pNew = sqliteMalloc(nByte); if( pNew==0 ){ return SQLITE_NOMEM; } memcpy(pNew, pMem->z, pMem->n); memset(&pNew[pMem->n], 0, pMem->u.i); @@ -409,10 +412,11 @@ void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){ sqlite3VdbeMemRelease(pMem); pMem->flags = MEM_Blob|MEM_Zero|MEM_Short; pMem->type = SQLITE_BLOB; pMem->n = 0; + if( n<0 ) n = 0; pMem->u.i = n; pMem->z = pMem->zShort; pMem->enc = SQLITE_UTF8; } Index: test/sqllimits1.test ================================================================== --- test/sqllimits1.test +++ test/sqllimits1.test @@ -10,11 +10,11 @@ #*********************************************************************** # # This file contains tests to verify that the limits defined in # sqlite source file limits.h are enforced. # -# $Id: sqllimits1.test,v 1.9 2007/06/07 15:45:35 danielk1977 Exp $ +# $Id: sqllimits1.test,v 1.10 2007/06/07 19:08:34 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Test organization: @@ -39,13 +39,16 @@ #-------------------------------------------------------------------- # Test cases sqllimits-1.* test that the SQLITE_MAX_LENGTH limit # is enforced. # -do_test sqllimits-1.1 { +do_test sqllimits-1.1.1 { catchsql { SELECT randomblob(2147483647) } } {1 {string or blob too big}} +do_test sqllimits-1.1.2 { + catchsql { SELECT zeroblob(2147483647) } +} {1 {string or blob too big}} # Large, but allowable, blob-size. # set ::LARGESIZE [expr $SQLITE_MAX_LENGTH - 1] @@ -56,10 +59,22 @@ do_test sqllimits-1.3 { catchsql { SELECT quote(randomblob($::LARGESIZE)) } } {1 {string or blob too big}} do_test sqllimits-1.4 { + catchsql { SELECT LENGTH(zeroblob($::LARGESIZE)) } +} "0 $::LARGESIZE" + +do_test sqllimits-1.5 { + catchsql { SELECT quote(zeroblob($::LARGESIZE)) } +} {1 {string or blob too big}} + +do_test sqllimits-1.6 { + catchsql { SELECT zeroblob(-1) } +} {0 {}} + +do_test sqllimits-1.9 { set ::str [string repeat A 65537] set ::rep [string repeat B 65537] catchsql { SELECT replace($::str, 'A', $::rep) } } {1 {string or blob too big}} @@ -435,7 +450,5 @@ SELECT strftime($::format, 1); } } {1 {string or blob too big}} finish_test - - Index: test/zeroblob.test ================================================================== --- test/zeroblob.test +++ test/zeroblob.test @@ -11,11 +11,11 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing of the zero-filled blob functionality # including the sqlite3_bind_zeroblob(), sqlite3_result_zeroblob(), # and the built-in zeroblob() SQL function. # -# $Id: zeroblob.test,v 1.5 2007/05/30 06:19:33 danielk1977 Exp $ +# $Id: zeroblob.test,v 1.6 2007/06/07 19:08:34 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !incrblob { @@ -149,7 +149,31 @@ execsql { SELECT CAST(zeroblob(100) AS BLOB); } } [execsql {SELECT zeroblob(100)}] + +# Check for malicious use of zeroblob. Make sure nothing crashes. +# +do_test zeroblob-6.1.1 { + execsql {select zeroblob(-1)} +} {{}} +do_test zeroblob-6.1.2 { + execsql {select zeroblob(-10)} +} {{}} +do_test zeroblob-6.1.3 { + execsql {select zeroblob(-100)} +} {{}} +do_test zeroblob-6.2 { + execsql {select length(zeroblob(-1))} +} {0} +do_test zeroblob-6.3 { + execsql {select zeroblob(-1)|1} +} {1} +do_test zeroblob-6.4 { + catchsql {select length(zeroblob(2147483648))} +} {1 {string or blob too big}} +do_test zeroblob-6.5 { + catchsql {select zeroblob(2147483648)} +} {1 {string or blob too big}} finish_test