summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordormando <dormando@rydia.net>2020-11-11 15:50:08 -0800
committerdormando <dormando@rydia.net>2020-11-11 15:50:08 -0800
commit19aac5aeca5aaf588dc58d5c04264c6be14ff7c0 (patch)
treed164bc933a89c40e76d5b89abe856a3c24a60e9e
parent27b73a4e272280b9a52bc1b098f758af69e28956 (diff)
downloadmemcached-19aac5aeca5aaf588dc58d5c04264c6be14ff7c0.tar.gz
portability fix for getsubopt
in the deferred IO patch I'd cribbed some code from another PR which turned out to use a non-portable return state from getsubopt. On BSD systems the subopts_value string is simply empty on a non-match. Fixing this portably looks gross but I couldn't come up with a better option... and frankly if we're going to pass options through DSO submodules in the future this is better anyway.
-rw-r--r--memcached.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/memcached.c b/memcached.c
index d84b0eb..e60f2c3 100644
--- a/memcached.c
+++ b/memcached.c
@@ -4952,6 +4952,11 @@ int main (int argc, char **argv) {
subopts_orig = subopts = strdup(optarg); /* getsubopt() changes the original args */
while (*subopts != '\0') {
+ // BSD getsubopt (at least) has undefined behavior on -1, so
+ // if we want to retry the getsubopt call in submodules we
+ // need an extra layer of string copies.
+ char *subopts_temp_o = NULL;
+ char *subopts_temp = subopts_temp_o = strdup(subopts);
switch (getsubopt(&subopts, subopts_tokens, &subopts_value)) {
case MAXCONNS_FAST:
@@ -5317,16 +5322,19 @@ int main (int argc, char **argv) {
default:
#ifdef EXTSTORE
// TODO: differentiating response code.
- if (storage_read_config(storage_cf, &subopts_value)) {
+ if (storage_read_config(storage_cf, &subopts_temp)) {
return 1;
}
#else
- printf("Illegal suboption \"%s\"\n", subopts_value);
+ printf("Illegal suboption \"%s\"\n", subopts_temp);
return 1;
#endif
+ } // switch
+ if (subopts_temp_o) {
+ free(subopts_temp_o);
}
- }
+ } // while
free(subopts_orig);
break;
default: