Index: src/func.c ================================================================== --- src/func.c +++ src/func.c @@ -229,22 +229,27 @@ sqlite3_value **argv ){ PrintfArguments x; StrAccum str; const char *zFormat; - int n; sqlite3 *db = sqlite3_context_db_handle(context); if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){ x.nArg = argc-1; x.nUsed = 0; x.apArg = argv+1; sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); sqlite3XPrintf(&str, SQLITE_PRINTF_SQLFUNC, zFormat, &x); - n = str.nChar; - sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, + sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar, SQLITE_DYNAMIC); + if( str.accError ){ + if( str.accError==STRACCUM_NOMEM ){ + sqlite3_result_error_nomem(context); + }else{ + sqlite3_result_error_toobig(context); + } + } } } /* ** Implementation of the substr() function. Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -2286,10 +2286,11 @@ SQLITE_MAX_ATTACHED, SQLITE_MAX_LIKE_PATTERN_LENGTH, SQLITE_MAX_VARIABLE_NUMBER, /* IMP: R-38091-32352 */ SQLITE_MAX_TRIGGER_DEPTH, SQLITE_MAX_WORKER_THREADS, + SQLITE_MAX_PRINTF_WIDTH, }; /* ** Make sure the hard limits are set to reasonable values */ @@ -2364,11 +2365,12 @@ assert( aHardLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]== SQLITE_MAX_LIKE_PATTERN_LENGTH ); assert( aHardLimit[SQLITE_LIMIT_VARIABLE_NUMBER]==SQLITE_MAX_VARIABLE_NUMBER); assert( aHardLimit[SQLITE_LIMIT_TRIGGER_DEPTH]==SQLITE_MAX_TRIGGER_DEPTH ); assert( aHardLimit[SQLITE_LIMIT_WORKER_THREADS]==SQLITE_MAX_WORKER_THREADS ); - assert( SQLITE_LIMIT_WORKER_THREADS==(SQLITE_N_LIMIT-1) ); + assert( aHardLimit[SQLITE_LIMIT_PRINTF_WIDTH]==SQLITE_MAX_PRINTF_WIDTH ); + assert( SQLITE_LIMIT_PRINTF_WIDTH==(SQLITE_N_LIMIT-1) ); if( limitId<0 || limitId>=SQLITE_N_LIMIT ){ return -1; } @@ -2730,10 +2732,11 @@ db->aDb = db->aDbStatic; assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); db->aLimit[SQLITE_LIMIT_WORKER_THREADS] = SQLITE_DEFAULT_WORKER_THREADS; + db->aLimit[SQLITE_LIMIT_PRINTF_WIDTH] = 10000; db->autoCommit = 1; db->nextAutovac = -1; db->szMmap = sqlite3GlobalConfig.szMmap; db->nextPagesize = 0; db->nMaxSorterMmap = 0x7FFFFFFF; Index: src/printf.c ================================================================== --- src/printf.c +++ src/printf.c @@ -299,10 +299,20 @@ precision = px & 0x7fffffff; } }else{ precision = -1; } + + /* Check for over-size width or precision and error-out if found */ + if( bArgList ){ + int iLimit = pAccum->db->aLimit[SQLITE_LIMIT_PRINTF_WIDTH]; + if( width>iLimit || precision>iLimit ){ + setStrAccumError(pAccum, STRACCUM_TOOBIG); + return; + } + } + /* Get the conversion type modifier */ if( c=='l' ){ flag_long = 1; c = *++fmt; if( c=='l' ){ Index: src/shell.c ================================================================== --- src/shell.c +++ src/shell.c @@ -3187,10 +3187,11 @@ { "attached", SQLITE_LIMIT_ATTACHED }, { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH }, { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER }, { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH }, { "worker_threads", SQLITE_LIMIT_WORKER_THREADS }, + { "printf_width", SQLITE_LIMIT_PRINTF_WIDTH }, }; int i, n2; open_db(p, 0); if( nArg==1 ){ for(i=0; iThe maximum depth of recursion for triggers.)^ ** ** [[SQLITE_LIMIT_WORKER_THREADS]] ^(
SQLITE_LIMIT_WORKER_THREADS
**
The maximum number of auxiliary worker threads that a single ** [prepared statement] may start.
)^ +** +** [[SQLITE_LIMIT_PRINTF_WIDTH]] ^(
SQLITE_LIMIT_PRINTF_WIDTH
+**
The maximum absolute value of the width or precision of a +** format specifier in the [printf SQL function].)^ ^Any invocation of +** the [printf SQL function] containing a width or precision larger than +** this limit (or smaller than the negative of this limit) causes an +** [SQLITE_TOOBIG] exception to be thrown.

This limit applies +** to the SQL function printf() only, and not to the various C-language +** printf-style interfaces such as [sqlite3_mprintf()]. For the C-language +** interfaces, the width and precision can be any 32-bit signed +** integer. ** */ #define SQLITE_LIMIT_LENGTH 0 #define SQLITE_LIMIT_SQL_LENGTH 1 #define SQLITE_LIMIT_COLUMN 2 @@ -3202,10 +3213,11 @@ #define SQLITE_LIMIT_ATTACHED 7 #define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8 #define SQLITE_LIMIT_VARIABLE_NUMBER 9 #define SQLITE_LIMIT_TRIGGER_DEPTH 10 #define SQLITE_LIMIT_WORKER_THREADS 11 +#define SQLITE_LIMIT_PRINTF_WIDTH 12 /* ** CAPI3REF: Compiling An SQL Statement ** KEYWORDS: {SQL statement compiler} ** METHOD: sqlite3 Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -1007,11 +1007,11 @@ /* ** The number of different kinds of things that can be limited ** using the sqlite3_limit() interface. */ -#define SQLITE_N_LIMIT (SQLITE_LIMIT_WORKER_THREADS+1) +#define SQLITE_N_LIMIT (SQLITE_LIMIT_PRINTF_WIDTH+1) /* ** Lookaside malloc is a set of fixed-size buffers that can be used ** to satisfy small transient memory allocation requests for objects ** associated with a particular database connection. The use of Index: src/sqliteLimit.h ================================================================== --- src/sqliteLimit.h +++ src/sqliteLimit.h @@ -206,5 +206,13 @@ ** may be executed. */ #ifndef SQLITE_MAX_TRIGGER_DEPTH # define SQLITE_MAX_TRIGGER_DEPTH 1000 #endif + +/* +** Maximum width or precision of a format specification in the SQL printf() +** function. +*/ +#ifndef SQLITE_MAX_PRINTF_WIDTH +# define SQLITE_MAX_PRINTF_WIDTH 0x7fffffff +#endif Index: src/test1.c ================================================================== --- src/test1.c +++ src/test1.c @@ -5449,14 +5449,15 @@ { "SQLITE_LIMIT_ATTACHED", SQLITE_LIMIT_ATTACHED }, { "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH }, { "SQLITE_LIMIT_VARIABLE_NUMBER", SQLITE_LIMIT_VARIABLE_NUMBER }, { "SQLITE_LIMIT_TRIGGER_DEPTH", SQLITE_LIMIT_TRIGGER_DEPTH }, { "SQLITE_LIMIT_WORKER_THREADS", SQLITE_LIMIT_WORKER_THREADS }, + { "SQLITE_LIMIT_PRINTF_WIDTH", SQLITE_LIMIT_PRINTF_WIDTH }, /* Out of range test cases */ { "SQLITE_LIMIT_TOOSMALL", -1, }, - { "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_WORKER_THREADS+1 }, + { "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_PRINTF_WIDTH+1 }, }; int i, id = 0; int val; const char *zId;