From: drh <> Date: Fri, 26 Sep 2025 13:14:20 +0000 (+0000) Subject: In the regexp extension, limit the maximum value of integers in the X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=80d74f09347372105731952acd47d79fd072a5d1;p=thirdparty%2Fsqlite.git In the regexp extension, limit the maximum value of integers in the "{p,q}" syntax, as performance of the NFA used to do pattern matching is linear in the maximum such integer. The limit is SQLITE_MAX_REGEXP_REPEAT which defaults to 999. This helps to prevent DoS attacks in systems that make use of the regexp extension. FossilOrigin-Name: 911c745f88c0ee8569e67bbcbbab034264f8c981b505aadac3ce7289486a1a68 --- diff --git a/ext/misc/regexp.c b/ext/misc/regexp.c index 447e403f80..cea94df144 100644 --- a/ext/misc/regexp.c +++ b/ext/misc/regexp.c @@ -26,7 +26,7 @@ ** X* zero or more occurrences of X ** X+ one or more occurrences of X ** X? zero or one occurrences of X -** X{p,q} between p and q occurrences of X +** X{p,q} between p and q occurrences of X, 0 <= p,q <= 999 ** (X) match X ** X|Y X or Y ** ^X X occurring at the beginning of the string @@ -55,12 +55,19 @@ ** to p copies of X following by q-p copies of X? and that the size of the ** regular expression in the O(N*M) performance bound is computed after ** this expansion. +** +** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax +** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999. */ #include #include #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 +#ifndef SQLITE_MAX_REGEXP_REPEAT +# define SQLITE_MAX_REGEXP_REPEAT 999 +#endif + /* ** The following #defines change the names of some functions implemented in ** this file to prevent name collisions with C-library functions of the @@ -566,12 +573,20 @@ static const char *re_subcompile_string(ReCompiled *p){ unsigned int m = 0, n = 0; unsigned int sz, j; if( iPrev<0 ) return "'{m,n}' without operand"; - while( (c=rePeek(p))>='0' && c<='9' ){ m = m*10 + c - '0'; p->sIn.i++; } + while( (c=rePeek(p))>='0' && c<='9' ){ + m = m*10 + c - '0'; + if( m>SQLITE_MAX_REGEXP_REPEAT ) return "integer too large"; + p->sIn.i++; + } n = m; if( c==',' ){ p->sIn.i++; n = 0; - while( (c=rePeek(p))>='0' && c<='9' ){ n = n*10 + c-'0'; p->sIn.i++; } + while( (c=rePeek(p))>='0' && c<='9' ){ + n = n*10 + c-'0'; + if( n>SQLITE_MAX_REGEXP_REPEAT ) return "integer too large"; + p->sIn.i++; + } } if( c!='}' ) return "unmatched '{'"; if( n