diff options
Diffstat (limited to 'hiredis.c')
-rw-r--r-- | hiredis.c | 88 |
1 files changed, 67 insertions, 21 deletions
@@ -770,33 +770,79 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) { while (*_p != '\0' && isdigit(*_p)) _p++; } - /* Modifiers */ - if (*_p != '\0') { - if (*_p == 'h' || *_p == 'l') { - /* Allow a single repetition for these modifiers */ - if (_p[0] == _p[1]) _p++; - _p++; + /* Copy va_list before consuming with va_arg */ + va_copy(_cpy,ap); + + /* Integer conversion (without modifiers) */ + if (strchr("diouxX",*_p) != NULL) { + va_arg(ap,int); + goto fmt_valid; + } + + /* Double conversion (without modifiers) */ + if (strchr("eEfFgGaA",*_p) != NULL) { + va_arg(ap,double); + goto fmt_valid; + } + + /* Size: char */ + if (_p[0] == 'h' && _p[1] == 'h') { + _p += 2; + if (*_p != '\0' && strchr("diouxX",*_p) != NULL) { + va_arg(ap,int); /* char gets promoted to int */ + goto fmt_valid; + } + goto fmt_invalid; + } + + /* Size: short */ + if (_p[0] == 'h') { + _p += 1; + if (*_p != '\0' && strchr("diouxX",*_p) != NULL) { + va_arg(ap,int); /* short gets promoted to int */ + goto fmt_valid; } + goto fmt_invalid; } - /* Conversion specifier */ - if (*_p != '\0' && strchr("diouxXeEfFgGaA",*_p) != NULL) { - _l = (_p+1)-c; - if (_l < sizeof(_format)-2) { - memcpy(_format,c,_l); - _format[_l] = '\0'; - va_copy(_cpy,ap); - newarg = sdscatvprintf(curarg,_format,_cpy); - va_end(_cpy); - - /* Update current position (note: outer blocks - * increment c twice so compensate here) */ - c = _p-1; + /* Size: long long */ + if (_p[0] == 'l' && _p[1] == 'l') { + _p += 2; + if (*_p != '\0' && strchr("diouxX",*_p) != NULL) { + va_arg(ap,long long); + goto fmt_valid; } + goto fmt_invalid; + } + + /* Size: long */ + if (_p[0] == 'l') { + _p += 1; + if (*_p != '\0' && strchr("diouxX",*_p) != NULL) { + va_arg(ap,long); + goto fmt_valid; + } + goto fmt_invalid; + } + + fmt_invalid: + va_end(_cpy); + goto err; + + fmt_valid: + _l = (_p+1)-c; + if (_l < sizeof(_format)-2) { + memcpy(_format,c,_l); + _format[_l] = '\0'; + newarg = sdscatvprintf(curarg,_format,_cpy); + + /* Update current position (note: outer blocks + * increment c twice so compensate here) */ + c = _p-1; } - /* Consume and discard vararg */ - va_arg(ap,void); + va_end(_cpy); + break; } } |