summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/config.c63
-rw-r--r--src/util.c66
-rw-r--r--src/util.h3
3 files changed, 78 insertions, 54 deletions
diff --git a/src/config.c b/src/config.c
index a83f5adc0..5b9616733 100644
--- a/src/config.c
+++ b/src/config.c
@@ -559,8 +559,8 @@ void loadServerConfigFromString(char *config) {
"an invalid one, or 'master' which has no buffer limits.";
goto loaderr;
}
- hard = memtoll(argv[2],NULL);
- soft = memtoll(argv[3],NULL);
+ hard = memtoull(argv[2],NULL);
+ soft = memtoull(argv[3],NULL);
soft_seconds = atoi(argv[4]);
if (soft_seconds < 0) {
err = "Negative number of seconds in soft limit is invalid";
@@ -744,8 +744,8 @@ void loadServerConfig(char *filename, char config_from_stdin, char *options) {
#define config_set_memory_field(_name,_var) \
} else if (!strcasecmp(c->argv[2]->ptr,_name)) { \
- ll = memtoll(o->ptr,&err); \
- if (err || ll < 0) goto badfmt; \
+ ll = memtoull(o->ptr,&err); \
+ if (err) goto badfmt; \
_var = ll;
#define config_set_special_field(_name) \
@@ -855,22 +855,26 @@ void configSetCommand(client *c) {
* whole configuration string or accept it all, even if a single
* error in a single client class is present. */
for (j = 0; j < vlen; j++) {
- long val;
-
if ((j % 4) == 0) {
int class = getClientTypeByName(v[j]);
- if (class == -1 || class == CLIENT_TYPE_MASTER) {
- sdsfreesplitres(v,vlen);
- goto badfmt;
- }
+ if (class == -1 || class == CLIENT_TYPE_MASTER)
+ break;
+ } else if ((j % 4) == 3) {
+ char *endptr;
+ long l = strtoll(v[j],&endptr,10);
+ if (l < 0 || *endptr != '\0')
+ break;
} else {
- val = memtoll(v[j], &err);
- if (err || val < 0) {
- sdsfreesplitres(v,vlen);
- goto badfmt;
- }
+ memtoull(v[j], &err);
+ if (err)
+ break;
}
}
+ if (j < vlen) {
+ sdsfreesplitres(v,vlen);
+ goto badfmt;
+ }
+
/* Finally set the new config */
for (j = 0; j < vlen; j += 4) {
int class;
@@ -878,8 +882,8 @@ void configSetCommand(client *c) {
int soft_seconds;
class = getClientTypeByName(v[j]);
- hard = memtoll(v[j+1],NULL);
- soft = memtoll(v[j+2],NULL);
+ hard = memtoull(v[j+1],NULL);
+ soft = memtoull(v[j+2],NULL);
soft_seconds = strtoll(v[j+3],NULL,10);
server.client_obuf_limits[class].hard_limit_bytes = hard;
@@ -2123,22 +2127,22 @@ static int numericBoundaryCheck(typeData data, long long ll, const char **err) {
return 1;
}
+
static int numericConfigSet(typeData data, sds value, int update, const char **err) {
long long ll, prev = 0;
if (data.numeric.is_memory) {
int memerr;
- ll = memtoll(value, &memerr);
- if (memerr || ll < 0) {
+ ll = memtoull(value, &memerr);
+ if (memerr) {
*err = "argument must be a memory value";
return 0;
}
} else {
- if (!string2ll(value, sdslen(value),&ll)) {
+ if (!string2ll(value, sdslen(value), &ll)) {
*err = "argument couldn't be parsed into an integer" ;
return 0;
}
}
-
if (!numericBoundaryCheck(data, ll, err))
return 0;
@@ -2157,12 +2161,21 @@ static int numericConfigSet(typeData data, sds value, int update, const char **e
static void numericConfigGet(client *c, typeData data) {
char buf[128];
- long long value = 0;
+ if (data.numeric.is_memory) {
+ unsigned long long value = 0;
+
+ GET_NUMERIC_TYPE(value)
- GET_NUMERIC_TYPE(value)
+ ull2string(buf, sizeof(buf), value);
+ addReplyBulkCString(c, buf);
+ } else{
+ long long value = 0;
+
+ GET_NUMERIC_TYPE(value)
- ll2string(buf, sizeof(buf), value);
- addReplyBulkCString(c, buf);
+ ll2string(buf, sizeof(buf), value);
+ addReplyBulkCString(c, buf);
+ }
}
static void numericConfigRewrite(typeData data, const char *name, struct rewriteConfigState *state) {
diff --git a/src/util.c b/src/util.c
index df7a489a5..d57420007 100644
--- a/src/util.c
+++ b/src/util.c
@@ -185,18 +185,19 @@ int stringmatchlen_fuzz_test(void) {
return total_matches;
}
+
/* Convert a string representing an amount of memory into the number of
- * bytes, so for instance memtoll("1Gb") will return 1073741824 that is
+ * bytes, so for instance memtoull("1Gb") will return 1073741824 that is
* (1024*1024*1024).
*
* On parsing error, if *err is not NULL, it's set to 1, otherwise it's
* set to 0. On error the function return value is 0, regardless of the
* fact 'err' is NULL or not. */
-long long memtoll(const char *p, int *err) {
+unsigned long long memtoull(const char *p, int *err) {
const char *u;
char buf[128];
long mul; /* unit multiplier */
- long long val;
+ unsigned long long val;
unsigned int digits;
if (err) *err = 0;
@@ -236,7 +237,7 @@ long long memtoll(const char *p, int *err) {
char *endptr;
errno = 0;
- val = strtoll(buf,&endptr,10);
+ val = strtoull(buf,&endptr,10);
if ((val == 0 && errno == EINVAL) || *endptr != '\0') {
if (err) *err = 1;
return 0;
@@ -307,26 +308,12 @@ uint32_t sdigits10(int64_t v) {
/* Convert a long long into a string. Returns the number of
* characters needed to represent the number.
- * If the buffer is not big enough to store the string, 0 is returned.
- *
- * Based on the following article (that apparently does not provide a
- * novel approach but only publicizes an already used technique):
- *
- * https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920
- *
- * Modified in order to handle signed integers since the original code was
- * designed for unsigned integers. */
+ * If the buffer is not big enough to store the string, 0 is returned. */
int ll2string(char *dst, size_t dstlen, long long svalue) {
- static const char digits[201] =
- "0001020304050607080910111213141516171819"
- "2021222324252627282930313233343536373839"
- "4041424344454647484950515253545556575859"
- "6061626364656667686970717273747576777879"
- "8081828384858687888990919293949596979899";
- int negative;
unsigned long long value;
+ int negative = 0;
- /* The main loop works with 64bit unsigned integers for simplicity, so
+ /* The ull2string function with 64bit unsigned integers for simplicity, so
* we convert the number here and remember if it is negative. */
if (svalue < 0) {
if (svalue != LLONG_MIN) {
@@ -334,20 +321,45 @@ int ll2string(char *dst, size_t dstlen, long long svalue) {
} else {
value = ((unsigned long long) LLONG_MAX)+1;
}
+ if (dstlen < 2)
+ return 0;
negative = 1;
+ dst[0] = '-';
+ dst++;
+ dstlen--;
} else {
value = svalue;
- negative = 0;
}
+ /* Converts the unsigned long long value to string*/
+ int length = ull2string(dst, dstlen, value);
+ if (length == 0) return 0;
+ return length + negative;
+}
+
+/* Convert a unsigned long long into a string. Returns the number of
+ * characters needed to represent the number.
+ * If the buffer is not big enough to store the string, 0 is returned.
+ *
+ * Based on the following article (that apparently does not provide a
+ * novel approach but only publicizes an already used technique):
+ *
+ * https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920 */
+int ull2string(char *dst, size_t dstlen, unsigned long long value) {
+ static const char digits[201] =
+ "0001020304050607080910111213141516171819"
+ "2021222324252627282930313233343536373839"
+ "4041424344454647484950515253545556575859"
+ "6061626364656667686970717273747576777879"
+ "8081828384858687888990919293949596979899";
+
/* Check length. */
- uint32_t const length = digits10(value)+negative;
+ uint32_t length = digits10(value);
if (length >= dstlen) return 0;
/* Null term. */
- uint32_t next = length;
- dst[next] = '\0';
- next--;
+ uint32_t next = length - 1;
+ dst[next + 1] = '\0';
while (value >= 100) {
int const i = (value % 100) * 2;
value /= 100;
@@ -365,8 +377,6 @@ int ll2string(char *dst, size_t dstlen, long long svalue) {
dst[next - 1] = digits[i];
}
- /* Add sign. */
- if (negative) dst[0] = '-';
return length;
}
diff --git a/src/util.h b/src/util.h
index bf2115ab7..e568ac6b3 100644
--- a/src/util.h
+++ b/src/util.h
@@ -48,12 +48,13 @@ typedef enum {
int stringmatchlen(const char *p, int plen, const char *s, int slen, int nocase);
int stringmatch(const char *p, const char *s, int nocase);
int stringmatchlen_fuzz_test(void);
-long long memtoll(const char *p, int *err);
+unsigned long long memtoull(const char *p, int *err);
const char *mempbrk(const char *s, size_t len, const char *chars, size_t charslen);
char *memmapchars(char *s, size_t len, const char *from, const char *to, size_t setlen);
uint32_t digits10(uint64_t v);
uint32_t sdigits10(int64_t v);
int ll2string(char *s, size_t len, long long value);
+int ull2string(char *s, size_t len, unsigned long long value);
int string2ll(const char *s, size_t slen, long long *value);
int string2ull(const char *s, unsigned long long *value);
int string2l(const char *s, size_t slen, long *value);