From patchwork Thu May 7 22:15:19 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Max Filippov X-Patchwork-Id: 469808 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from hemlock.osuosl.org (hemlock.osuosl.org [140.211.166.133]) by ozlabs.org (Postfix) with ESMTP id BFE251401B5 for ; Fri, 8 May 2015 08:15:41 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=YFPQrW67; dkim-atps=neutral Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id D8C9B950A1; Thu, 7 May 2015 22:15:39 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id WjWIiFwyhddX; Thu, 7 May 2015 22:15:37 +0000 (UTC) Received: from ash.osuosl.org (ash.osuosl.org [140.211.166.34]) by hemlock.osuosl.org (Postfix) with ESMTP id EDD439509C; Thu, 7 May 2015 22:15:36 +0000 (UTC) X-Original-To: uclibc@lists.busybox.net Delivered-To: uclibc@osuosl.org Received: from silver.osuosl.org (silver.osuosl.org [140.211.166.136]) by ash.osuosl.org (Postfix) with ESMTP id 490F21BF83A for ; Thu, 7 May 2015 22:15:36 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 4544223FBA for ; Thu, 7 May 2015 22:15:36 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from silver.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 1PROXf+hgo+A for ; Thu, 7 May 2015 22:15:34 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mail-la0-f47.google.com (mail-la0-f47.google.com [209.85.215.47]) by silver.osuosl.org (Postfix) with ESMTPS id 242B82341E for ; Thu, 7 May 2015 22:15:34 +0000 (UTC) Received: by laat2 with SMTP id t2so40807847laa.1 for ; Thu, 07 May 2015 15:15:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=8HRICRKtTYzSZdwzTDnbvwA+OKsimRXBWcXTyDTgVNU=; b=YFPQrW67XFGdtsfbptj/+RXmcqjr0zeFLga575sqvzseDjhJ9d805/AMHxBYUtzCIO /iI5DB5dKXKVfrNPUbbSiiWhxtZhyNVUSiwm+lN4R//YaI++7+BgbX9F8wsh8IzEt4kp R4q3cfgK6AsL5Syld87PDNzbk0EVOJI07ngtm+J3lqKa8puiE+DPyzgNrwfFUvkYuEiO C7oswCZjJGCRmYjNJFom6c5gPRhWbARk+jT9o4WZk2zyMEIPfGG+SamfyDfo2m2xdMie FldZoEjsU0p28NT1E8TBpcPj2NHBXwSiVLDxODXe0+P/GEo1dClhd7O0GSFqhxA760Q7 j/lw== X-Received: by 10.112.167.73 with SMTP id zm9mr542424lbb.89.1431036931088; Thu, 07 May 2015 15:15:31 -0700 (PDT) Received: from octofox.metropolis ([5.19.183.212]) by mx.google.com with ESMTPSA id m8sm734262lbs.17.2015.05.07.15.15.29 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 07 May 2015 15:15:30 -0700 (PDT) From: Max Filippov To: uclibc@uclibc.org Subject: [PATCH v2] _scanf.c: Implement 'm' modifier for 'c' and '[' conversions. Date: Fri, 8 May 2015 01:15:19 +0300 Message-Id: <1431036919-4088-1-git-send-email-jcmvbkbc@gmail.com> X-Mailer: git-send-email 1.8.1.4 Cc: Will Newton X-BeenThere: uclibc@uclibc.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "Discussion and development of uClibc \(the embedded C library\)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: uclibc-bounces@uclibc.org Sender: "uClibc" From: Will Newton The current code implements the 'm' modifier only for 's' conversions and would cause a segfault if it was used for 'c' or '[' conversions. This patch extends the code to cover these cases too. The original version could write scanned data outside the passed buffer because index i used in the '[' conversion handling block was clobbered. Signed-off-by: Will Newton Signed-off-by: Max Filippov --- Changes v1->v2: - add testcase for %[...]/%c/%m[...]/%mc. libc/stdio/_scanf.c | 51 +++++++++++++++++++++++++++++++++------------------ test/stdio/scanf_m.c | 24 ++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 18 deletions(-) create mode 100644 test/stdio/scanf_m.c diff --git a/libc/stdio/_scanf.c b/libc/stdio/_scanf.c index 6ecb3cb..a5828c3 100644 --- a/libc/stdio/_scanf.c +++ b/libc/stdio/_scanf.c @@ -1352,7 +1352,20 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg) (psfs.conv_num >= CONV_c) #endif /* __UCLIBC_HAS_WCHAR__ */ { + /* We might have to handle the allocation ourselves */ + int len; + unsigned char **ptr; + b = (psfs.store ? ((unsigned char *) psfs.cur_ptr) : buf); + /* With 'm', we actually got a pointer to a pointer */ + ptr = (void *)b; + + if (psfs.flags & FLAG_MALLOC) { + len = 0; + b = NULL; + } else + len = -1; + fail = 1; if (psfs.conv_num == CONV_c) { @@ -1360,32 +1373,28 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg) sc.width = 1; } + if (psfs.flags & FLAG_MALLOC) + b = malloc(sc.width); + + i = 0; while (__scan_getc(&sc) >= 0) { zero_conversions = 0; - *b = sc.cc; - b += psfs.store; + b[i] = sc.cc; + i += psfs.store; } __scan_ungetc(&sc); if (sc.width > 0) { /* Failed to read all required. */ goto DONE; } + if (psfs.flags & FLAG_MALLOC) + *ptr = b; psfs.cnt += psfs.store; goto NEXT_FMT; } if (psfs.conv_num == CONV_s) { - /* We might have to handle the allocation ourselves */ - int len; - /* With 'm', we actually got a pointer to a pointer */ - unsigned char **ptr = (void *)b; i = 0; - if (psfs.flags & FLAG_MALLOC) { - len = 0; - b = NULL; - } else - len = -1; - /* Yes, believe it or not, a %s conversion can store nuls. */ while ((__scan_getc(&sc) >= 0) && !isspace(sc.cc)) { zero_conversions = 0; @@ -1400,10 +1409,6 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg) fail = 0; } - if (psfs.flags & FLAG_MALLOC) - *ptr = b; - /* The code below takes care of terminating NUL */ - b += i; } else { #ifdef __UCLIBC_HAS_WCHAR__ assert((psfs.conv_num == CONV_LEFTBRACKET) || \ @@ -1454,13 +1459,20 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg) #endif /* __UCLIBC_HAS_WCHAR__ */ + i = 0; while (__scan_getc(&sc) >= 0) { zero_conversions = 0; if (!scanset[sc.cc]) { break; } - *b = sc.cc; - b += psfs.store; + if (i == len) { + /* Pick a size that won't trigger a lot of + * mallocs early on ... */ + len += 256; + b = realloc(b, len + 1); + } + b[i] = sc.cc; + i += psfs.store; fail = 0; } } @@ -1470,6 +1482,9 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg) if (fail) { /* nothing stored! */ goto DONE; } + if (psfs.flags & FLAG_MALLOC) + *ptr = b; + b += i; *b = 0; /* Nul-terminate string. */ psfs.cnt += psfs.store; goto NEXT_FMT; diff --git a/test/stdio/scanf_m.c b/test/stdio/scanf_m.c new file mode 100644 index 0000000..0ce78b6 --- /dev/null +++ b/test/stdio/scanf_m.c @@ -0,0 +1,24 @@ +#include +#include +#include + +int main(void) +{ + const char *buf = "hello world"; + char *ps = NULL, *pc = NULL; + char s[6], c; + + /* Check that %[...]/%c work. */ + sscanf(buf, "%[a-z] %c", s, &c); + /* Check that %m[...]/%mc work. */ + sscanf(buf, "%m[a-z] %mc", &ps, &pc); + + if (strcmp(ps, "hello") != 0 || *pc != 'w' || + strcmp(s, "hello") != 0 || c != 'w') + return 1; + + free(ps); + free(pc); + + return 0; +}