From patchwork Thu Jan 19 18:22:38 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: DJ Delorie X-Patchwork-Id: 18956 Received: (qmail 16292 invoked by alias); 19 Jan 2017 18:22:43 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 16282 invoked by uid 89); 19 Jan 2017 18:22:42 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-5.1 required=5.0 tests=BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=fff, Hx-languages-length:2228 X-HELO: mx1.redhat.com Date: Thu, 19 Jan 2017 13:22:38 -0500 Message-Id: From: DJ Delorie To: libc-alpha@sourceware.org Subject: tunables signed/unsigned bug & patch The range check for size_t tunables was checking against (signed)(0xfff...fff), which is -1, so never passed (val>0 && val<-1). This means half the existing tunables would never work :-( I couldn't think of a clean way to handle both signed and unsigned in the same function, so I split it into separate functions. As an aside, tunables_strtoul() parses signed values but returns unsigned values. Ideally that would be split out too, but that's a lot more code duplication. DJ diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c index e0119d1..c2f487a 100644 --- a/elf/dl-tunables.c +++ b/elf/dl-tunables.c @@ -172,10 +172,10 @@ tunables_strtoul (const char *nptr) explicit constraints of the tunable or with the implicit constraints of its type. */ static void -tunable_set_val_if_valid_range (tunable_t *cur, const char *strval, +tunable_set_val_if_valid_range_signed (tunable_t *cur, const char *strval, int64_t default_min, int64_t default_max) { - int64_t val = tunables_strtoul (strval); + int64_t val = (int64_t) tunables_strtoul (strval); int64_t min = cur->type.min; int64_t max = cur->type.max; @@ -193,6 +193,28 @@ tunable_set_val_if_valid_range (tunable_t *cur, const char *strval, } } +static void +tunable_set_val_if_valid_range_unsigned (tunable_t *cur, const char *strval, + uint64_t default_min, uint64_t default_max) +{ + uint64_t val = (uint64_t) tunables_strtoul (strval); + + uint64_t min = cur->type.min; + uint64_t max = cur->type.max; + + if (min == max) + { + min = default_min; + max = default_max; + } + + if (val >= min && val <= max) + { + cur->val.numval = val; + cur->strval = strval; + } +} + /* Validate range of the input value and initialize the tunable CUR if it looks good. */ static void @@ -202,12 +224,12 @@ tunable_initialize (tunable_t *cur, const char *strval) { case TUNABLE_TYPE_INT_32: { - tunable_set_val_if_valid_range (cur, strval, INT32_MIN, INT32_MAX); + tunable_set_val_if_valid_range_signed (cur, strval, INT32_MIN, INT32_MAX); break; } case TUNABLE_TYPE_SIZE_T: { - tunable_set_val_if_valid_range (cur, strval, 0, SIZE_MAX); + tunable_set_val_if_valid_range_unsigned (cur, strval, 0, SIZE_MAX); break; } case TUNABLE_TYPE_STRING: