/ Check-in [f8b15979]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add the SQLITE_LIMIT_PRINTF_WIDTH setting for sqlite3_limit() and associated logic for preventing DOS attacks using printf() with oversized widths or precisions.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | limit-printf-width
Files: files | file ages | folders
SHA1: f8b159794c3855cad86d755cc7422ddc21722200
User & Date: drh 2015-05-02 18:25:25
Context
2015-05-02
18:25
Add the SQLITE_LIMIT_PRINTF_WIDTH setting for sqlite3_limit() and associated logic for preventing DOS attacks using printf() with oversized widths or precisions. Leaf check-in: f8b15979 user: drh tags: limit-printf-width
17:40
Add the ".limit" command to the command-line shell. check-in: 803cb60e user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/func.c.

   227    227     sqlite3_context *context,
   228    228     int argc,
   229    229     sqlite3_value **argv
   230    230   ){
   231    231     PrintfArguments x;
   232    232     StrAccum str;
   233    233     const char *zFormat;
   234         -  int n;
   235    234     sqlite3 *db = sqlite3_context_db_handle(context);
   236    235   
   237    236     if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){
   238    237       x.nArg = argc-1;
   239    238       x.nUsed = 0;
   240    239       x.apArg = argv+1;
   241    240       sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
   242    241       sqlite3XPrintf(&str, SQLITE_PRINTF_SQLFUNC, zFormat, &x);
   243         -    n = str.nChar;
   244         -    sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
          242  +    sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar,
   245    243                           SQLITE_DYNAMIC);
          244  +    if( str.accError ){
          245  +      if( str.accError==STRACCUM_NOMEM ){
          246  +        sqlite3_result_error_nomem(context);
          247  +      }else{
          248  +        sqlite3_result_error_toobig(context);
          249  +      }
          250  +    }
   246    251     }
   247    252   }
   248    253   
   249    254   /*
   250    255   ** Implementation of the substr() function.
   251    256   **
   252    257   ** substr(x,p1,p2)  returns p2 characters of x[] beginning with p1.

Changes to src/main.c.

  2284   2284     SQLITE_MAX_VDBE_OP,
  2285   2285     SQLITE_MAX_FUNCTION_ARG,
  2286   2286     SQLITE_MAX_ATTACHED,
  2287   2287     SQLITE_MAX_LIKE_PATTERN_LENGTH,
  2288   2288     SQLITE_MAX_VARIABLE_NUMBER,      /* IMP: R-38091-32352 */
  2289   2289     SQLITE_MAX_TRIGGER_DEPTH,
  2290   2290     SQLITE_MAX_WORKER_THREADS,
         2291  +  SQLITE_MAX_PRINTF_WIDTH,
  2291   2292   };
  2292   2293   
  2293   2294   /*
  2294   2295   ** Make sure the hard limits are set to reasonable values
  2295   2296   */
  2296   2297   #if SQLITE_MAX_LENGTH<100
  2297   2298   # error SQLITE_MAX_LENGTH must be at least 100
................................................................................
  2362   2363     assert( aHardLimit[SQLITE_LIMIT_FUNCTION_ARG]==SQLITE_MAX_FUNCTION_ARG );
  2363   2364     assert( aHardLimit[SQLITE_LIMIT_ATTACHED]==SQLITE_MAX_ATTACHED );
  2364   2365     assert( aHardLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]==
  2365   2366                                                  SQLITE_MAX_LIKE_PATTERN_LENGTH );
  2366   2367     assert( aHardLimit[SQLITE_LIMIT_VARIABLE_NUMBER]==SQLITE_MAX_VARIABLE_NUMBER);
  2367   2368     assert( aHardLimit[SQLITE_LIMIT_TRIGGER_DEPTH]==SQLITE_MAX_TRIGGER_DEPTH );
  2368   2369     assert( aHardLimit[SQLITE_LIMIT_WORKER_THREADS]==SQLITE_MAX_WORKER_THREADS );
  2369         -  assert( SQLITE_LIMIT_WORKER_THREADS==(SQLITE_N_LIMIT-1) );
         2370  +  assert( aHardLimit[SQLITE_LIMIT_PRINTF_WIDTH]==SQLITE_MAX_PRINTF_WIDTH );
         2371  +  assert( SQLITE_LIMIT_PRINTF_WIDTH==(SQLITE_N_LIMIT-1) );
  2370   2372   
  2371   2373   
  2372   2374     if( limitId<0 || limitId>=SQLITE_N_LIMIT ){
  2373   2375       return -1;
  2374   2376     }
  2375   2377     oldLimit = db->aLimit[limitId];
  2376   2378     if( newLimit>=0 ){                   /* IMP: R-52476-28732 */
................................................................................
  2728   2730     db->nDb = 2;
  2729   2731     db->magic = SQLITE_MAGIC_BUSY;
  2730   2732     db->aDb = db->aDbStatic;
  2731   2733   
  2732   2734     assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
  2733   2735     memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
  2734   2736     db->aLimit[SQLITE_LIMIT_WORKER_THREADS] = SQLITE_DEFAULT_WORKER_THREADS;
         2737  +  db->aLimit[SQLITE_LIMIT_PRINTF_WIDTH] = 10000;
  2735   2738     db->autoCommit = 1;
  2736   2739     db->nextAutovac = -1;
  2737   2740     db->szMmap = sqlite3GlobalConfig.szMmap;
  2738   2741     db->nextPagesize = 0;
  2739   2742     db->nMaxSorterMmap = 0x7FFFFFFF;
  2740   2743     db->flags |= SQLITE_ShortColNames | SQLITE_EnableTrigger | SQLITE_CacheSpill
  2741   2744   #if !defined(SQLITE_DEFAULT_AUTOMATIC_INDEX) || SQLITE_DEFAULT_AUTOMATIC_INDEX

Changes to src/printf.c.

   297    297           }
   298    298           testcase( px>0x7fffffff );
   299    299           precision = px & 0x7fffffff;
   300    300         }
   301    301       }else{
   302    302         precision = -1;
   303    303       }
          304  +
          305  +    /* Check for over-size width or precision and error-out if found */
          306  +    if( bArgList ){
          307  +      int iLimit = pAccum->db->aLimit[SQLITE_LIMIT_PRINTF_WIDTH];
          308  +      if( width>iLimit || precision>iLimit ){
          309  +        setStrAccumError(pAccum, STRACCUM_TOOBIG);
          310  +        return;
          311  +      }
          312  +    }
          313  +
   304    314       /* Get the conversion type modifier */
   305    315       if( c=='l' ){
   306    316         flag_long = 1;
   307    317         c = *++fmt;
   308    318         if( c=='l' ){
   309    319           flag_longlong = 1;
   310    320           c = *++fmt;

Changes to src/shell.c.

  3185   3185         { "vdbe_op",               SQLITE_LIMIT_VDBE_OP                   },
  3186   3186         { "function_arg",          SQLITE_LIMIT_FUNCTION_ARG              },
  3187   3187         { "attached",              SQLITE_LIMIT_ATTACHED                  },
  3188   3188         { "like_pattern_length",   SQLITE_LIMIT_LIKE_PATTERN_LENGTH       },
  3189   3189         { "variable_number",       SQLITE_LIMIT_VARIABLE_NUMBER           },
  3190   3190         { "trigger_depth",         SQLITE_LIMIT_TRIGGER_DEPTH             },
  3191   3191         { "worker_threads",        SQLITE_LIMIT_WORKER_THREADS            },
         3192  +      { "printf_width",          SQLITE_LIMIT_PRINTF_WIDTH              },
  3192   3193       };
  3193   3194       int i, n2;
  3194   3195       open_db(p, 0);
  3195   3196       if( nArg==1 ){
  3196   3197         for(i=0; i<sizeof(aLimit)/sizeof(aLimit[0]); i++){
  3197   3198           printf("%20s %d\n", aLimit[i].zLimitName, 
  3198   3199                  sqlite3_limit(p->db, aLimit[i].limitCode, -1));

Changes to src/sqlite.h.in.

  3186   3186   **
  3187   3187   ** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
  3188   3188   ** <dd>The maximum depth of recursion for triggers.</dd>)^
  3189   3189   **
  3190   3190   ** [[SQLITE_LIMIT_WORKER_THREADS]] ^(<dt>SQLITE_LIMIT_WORKER_THREADS</dt>
  3191   3191   ** <dd>The maximum number of auxiliary worker threads that a single
  3192   3192   ** [prepared statement] may start.</dd>)^
         3193  +**
         3194  +** [[SQLITE_LIMIT_PRINTF_WIDTH]] ^(<dt>SQLITE_LIMIT_PRINTF_WIDTH</dt>
         3195  +** <dd>The maximum absolute value of the width or precision of a
         3196  +** format specifier in the [printf SQL function].)^  ^Any invocation of
         3197  +** the [printf SQL function] containing a width or precision larger than
         3198  +** this limit (or smaller than the negative of this limit) causes an
         3199  +** [SQLITE_TOOBIG] exception to be thrown.  <p>This limit applies
         3200  +** to the SQL function printf() only, and not to the various C-language
         3201  +** printf-style interfaces such as [sqlite3_mprintf()].  For the C-language
         3202  +** interfaces, the width and precision can be any 32-bit signed
         3203  +** integer.
  3193   3204   ** </dl>
  3194   3205   */
  3195   3206   #define SQLITE_LIMIT_LENGTH                    0
  3196   3207   #define SQLITE_LIMIT_SQL_LENGTH                1
  3197   3208   #define SQLITE_LIMIT_COLUMN                    2
  3198   3209   #define SQLITE_LIMIT_EXPR_DEPTH                3
  3199   3210   #define SQLITE_LIMIT_COMPOUND_SELECT           4
................................................................................
  3200   3211   #define SQLITE_LIMIT_VDBE_OP                   5
  3201   3212   #define SQLITE_LIMIT_FUNCTION_ARG              6
  3202   3213   #define SQLITE_LIMIT_ATTACHED                  7
  3203   3214   #define SQLITE_LIMIT_LIKE_PATTERN_LENGTH       8
  3204   3215   #define SQLITE_LIMIT_VARIABLE_NUMBER           9
  3205   3216   #define SQLITE_LIMIT_TRIGGER_DEPTH            10
  3206   3217   #define SQLITE_LIMIT_WORKER_THREADS           11
         3218  +#define SQLITE_LIMIT_PRINTF_WIDTH             12
  3207   3219   
  3208   3220   /*
  3209   3221   ** CAPI3REF: Compiling An SQL Statement
  3210   3222   ** KEYWORDS: {SQL statement compiler}
  3211   3223   ** METHOD: sqlite3
  3212   3224   ** CONSTRUCTOR: sqlite3_stmt
  3213   3225   **

Changes to src/sqliteInt.h.

  1005   1005   #define DB_UnresetViews    0x0002  /* Some views have defined column names */
  1006   1006   #define DB_Empty           0x0004  /* The file is empty (length 0 bytes) */
  1007   1007   
  1008   1008   /*
  1009   1009   ** The number of different kinds of things that can be limited
  1010   1010   ** using the sqlite3_limit() interface.
  1011   1011   */
  1012         -#define SQLITE_N_LIMIT (SQLITE_LIMIT_WORKER_THREADS+1)
         1012  +#define SQLITE_N_LIMIT (SQLITE_LIMIT_PRINTF_WIDTH+1)
  1013   1013   
  1014   1014   /*
  1015   1015   ** Lookaside malloc is a set of fixed-size buffers that can be used
  1016   1016   ** to satisfy small transient memory allocation requests for objects
  1017   1017   ** associated with a particular database connection.  The use of
  1018   1018   ** lookaside malloc provides a significant performance enhancement
  1019   1019   ** (approx 10%) by avoiding numerous malloc/free requests while parsing

Changes to src/sqliteLimit.h.

   204    204   ** A value of 1 means that a trigger program will not be able to itself
   205    205   ** fire any triggers. A value of 0 means that no trigger programs at all 
   206    206   ** may be executed.
   207    207   */
   208    208   #ifndef SQLITE_MAX_TRIGGER_DEPTH
   209    209   # define SQLITE_MAX_TRIGGER_DEPTH 1000
   210    210   #endif
          211  +
          212  +/*
          213  +** Maximum width or precision of a format specification in the SQL printf()
          214  +** function.
          215  +*/
          216  +#ifndef SQLITE_MAX_PRINTF_WIDTH
          217  +# define SQLITE_MAX_PRINTF_WIDTH 0x7fffffff
          218  +#endif

Changes to src/test1.c.

  5447   5447       { "SQLITE_LIMIT_VDBE_OP",             SQLITE_LIMIT_VDBE_OP              },
  5448   5448       { "SQLITE_LIMIT_FUNCTION_ARG",        SQLITE_LIMIT_FUNCTION_ARG         },
  5449   5449       { "SQLITE_LIMIT_ATTACHED",            SQLITE_LIMIT_ATTACHED             },
  5450   5450       { "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH  },
  5451   5451       { "SQLITE_LIMIT_VARIABLE_NUMBER",     SQLITE_LIMIT_VARIABLE_NUMBER      },
  5452   5452       { "SQLITE_LIMIT_TRIGGER_DEPTH",       SQLITE_LIMIT_TRIGGER_DEPTH        },
  5453   5453       { "SQLITE_LIMIT_WORKER_THREADS",      SQLITE_LIMIT_WORKER_THREADS       },
         5454  +    { "SQLITE_LIMIT_PRINTF_WIDTH",        SQLITE_LIMIT_PRINTF_WIDTH         },
  5454   5455       
  5455   5456       /* Out of range test cases */
  5456   5457       { "SQLITE_LIMIT_TOOSMALL",            -1,                               },
  5457         -    { "SQLITE_LIMIT_TOOBIG",              SQLITE_LIMIT_WORKER_THREADS+1     },
         5458  +    { "SQLITE_LIMIT_TOOBIG",              SQLITE_LIMIT_PRINTF_WIDTH+1       },
  5458   5459     };
  5459   5460     int i, id = 0;
  5460   5461     int val;
  5461   5462     const char *zId;
  5462   5463   
  5463   5464     if( objc!=4 ){
  5464   5465       Tcl_AppendResult(interp, "wrong # args: should be \"",