diff --git a/src/functions.c b/src/functions.c index aa71c19e3..8da845250 100644 --- a/src/functions.c +++ b/src/functions.c @@ -54,10 +54,10 @@ dictType engineDictType = { }; dictType functionDictType = { - dictSdsHash, /* hash function */ + dictSdsCaseHash, /* hash function */ dictSdsDup, /* key dup */ NULL, /* val dup */ - dictSdsKeyCompare, /* key compare */ + dictSdsKeyCaseCompare,/* key compare */ dictSdsDestructor, /* key destructor */ engineFunctionDispose,/* val destructor */ NULL /* allow to expand */ @@ -438,10 +438,34 @@ NULL }; addReplyHelp(c, help); } +/* Verify that the function name is of the format: [a-zA-Z0-9_][a-zA-Z0-9_]? */ +static int functionsVerifyName(sds name) { + if (sdslen(name) == 0) { + return C_ERR; + } + for (size_t i = 0 ; i < sdslen(name) ; ++i) { + char curr_char = name[i]; + if ((curr_char >= 'a' && curr_char <= 'z') || + (curr_char >= 'A' && curr_char <= 'Z') || + (curr_char >= '0' && curr_char <= '9') || + (curr_char == '_')) + { + continue; + } + return C_ERR; + } + return C_OK; +} + /* Compile and save the given function, return C_OK on success and C_ERR on failure. * In case on failure the err out param is set with relevant error message */ int functionsCreateWithFunctionCtx(sds function_name,sds engine_name, sds desc, sds code, int replace, sds* err, functionsCtx *functions) { + if (functionsVerifyName(function_name)) { + *err = sdsnew("Function names can only contain letters and numbers and must be at least one character long"); + return C_ERR; + } + engineInfo *ei = dictFetchValue(engines, engine_name); if (!ei) { *err = sdsnew("Engine not found"); diff --git a/tests/unit/functions.tcl b/tests/unit/functions.tcl index a49739a53..2ba8ae70e 100644 --- a/tests/unit/functions.tcl +++ b/tests/unit/functions.tcl @@ -11,6 +11,20 @@ start_server {tags {"scripting"}} { set _ $e } {*Function already exists*} + test {FUNCTION - Create an already exiting function raise error (case insensitive)} { + catch { + r function create LUA TEST {return 'hello1'} + } e + set _ $e + } {*Function already exists*} + + test {FUNCTION - Create a function with wrong name format} { + catch { + r function create LUA {bad\0foramat} {return 'hello1'} + } e + set _ $e + } {*Function names can only contain letters and numbers*} + test {FUNCTION - Create function with unexisting engine} { catch { r function create bad_engine test {return 'hello1'} @@ -30,6 +44,10 @@ start_server {tags {"scripting"}} { r fcall test 0 } {hello1} + test {FUNCTION - test function case insensitive} { + r fcall TEST 0 + } {hello1} + test {FUNCTION - test replace argument with function creation failure keeps old function} { catch {r function create LUA test REPLACE {error}} r fcall test 0