diff --git a/deps/lua/src/lua_bit.c b/deps/lua/src/lua_bit.c index 9f83b8594b..7e43faea47 100644 --- a/deps/lua/src/lua_bit.c +++ b/deps/lua/src/lua_bit.c @@ -132,6 +132,7 @@ static int bit_tohex(lua_State *L) const char *hexdigits = "0123456789abcdef"; char buf[8]; int i; + if (n == INT32_MIN) n = INT32_MIN+1; if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; } if (n > 8) n = 8; for (i = (int)n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; } diff --git a/src/acl.c b/src/acl.c index 17632df0d4..14d9c6e6f3 100644 --- a/src/acl.c +++ b/src/acl.c @@ -1079,7 +1079,7 @@ int ACLSetSelector(aclSelector *selector, const char *op, size_t oplen) { flags |= ACL_READ_PERMISSION; } else if (toupper(op[offset]) == 'W' && !(flags & ACL_WRITE_PERMISSION)) { flags |= ACL_WRITE_PERMISSION; - } else if (op[offset] == '~') { + } else if (op[offset] == '~' && flags) { offset++; break; } else { diff --git a/src/util.c b/src/util.c index 66f62c9001..b1235c2822 100644 --- a/src/util.c +++ b/src/util.c @@ -59,7 +59,11 @@ static int stringmatchlen_impl(const char *pattern, const char *string, int stringLen, int nocase, - int *skipLongerMatches) { + int *skipLongerMatches, + int nesting) { + /* Protection against abusive patterns. */ + if (nesting > 1000) return 0; + while (patternLen && stringLen) { switch (pattern[0]) { case '*': @@ -69,7 +73,8 @@ static int stringmatchlen_impl(const char *pattern, } if (patternLen == 1) return 1; /* match */ while (stringLen) { - if (stringmatchlen_impl(pattern + 1, patternLen - 1, string, stringLen, nocase, skipLongerMatches)) + if (stringmatchlen_impl(pattern + 1, patternLen - 1, string, stringLen, nocase, skipLongerMatches, + nesting + 1)) return 1; /* match */ if (*skipLongerMatches) return 0; /* no match */ string++; @@ -179,7 +184,7 @@ static int stringmatchlen_impl(const char *pattern, int stringmatchlen(const char *pattern, int patternLen, const char *string, int stringLen, int nocase) { int skipLongerMatches = 0; - return stringmatchlen_impl(pattern, patternLen, string, stringLen, nocase, &skipLongerMatches); + return stringmatchlen_impl(pattern, patternLen, string, stringLen, nocase, &skipLongerMatches, 0); } int stringmatch(const char *pattern, const char *string, int nocase) { diff --git a/tests/unit/acl-v2.tcl b/tests/unit/acl-v2.tcl index 9827c0ba02..a509bc0ff6 100644 --- a/tests/unit/acl-v2.tcl +++ b/tests/unit/acl-v2.tcl @@ -116,6 +116,11 @@ start_server {tags {"acl external:skip"}} { assert_match "*NOPERM*key*" $err } + test {Validate read and write permissions format} { + catch {r ACL SETUSER key-permission-RW %~} err + set err + } {ERR Error in ACL SETUSER modifier '%~': Syntax error} + test {Test separate read and write permissions on different selectors are not additive} { r ACL SETUSER key-permission-RW-selector on nopass "(%R~read* +@all)" "(%W~write* +@all)" $r2 auth key-permission-RW-selector password diff --git a/tests/unit/keyspace.tcl b/tests/unit/keyspace.tcl index c8bdcac984..ba55c1b8ea 100644 --- a/tests/unit/keyspace.tcl +++ b/tests/unit/keyspace.tcl @@ -547,4 +547,10 @@ foreach {type large} [array get largevalue] { assert_no_match "*db2:keys=*" [r info keyspace] r flushall } {OK} {singledb:skip} + + test {Regression for pattern matching very long nested loops} { + r flushdb + r SET [string repeat "a" 50000] 1 + r KEYS [string repeat "*?" 50000] + } {} } diff --git a/tests/unit/scripting.tcl b/tests/unit/scripting.tcl index 1a73b9d1ab..db37129103 100644 --- a/tests/unit/scripting.tcl +++ b/tests/unit/scripting.tcl @@ -733,6 +733,12 @@ start_server {tags {"scripting"}} { set e } {ERR *Attempt to modify a readonly table*} + test {lua bit.tohex bug} { + set res [run_script {return bit.tohex(65535, -2147483648)} 0] + r ping + set res + } {0000FFFF} + test {Test an example script DECR_IF_GT} { set decr_if_gt { local current