From patchwork Fri Apr 1 19:19:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frolov Daniil X-Patchwork-Id: 52584 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 226173857C71 for ; Fri, 1 Apr 2022 19:20:32 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 226173857C71 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1648840832; bh=ZiD2uA25iy8aGkXg3gjJWkeM2bwbdoZPkOewKuX7IpI=; h=Date:Subject:To:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=f3AZNaV4WWuTQ/q14Hu7iRovf2ulw4w/+HDZnXev4NxgFrKnCY/HjM8XGuUOdX7z8 VGCecnXJdjjFh3Me8bS8XZoe/LwG99ri3E5ZLvqE4PffHamAydB7eRSE3vY584W7Jm FRLsFiK/NV3mHv/iT98v2SGUmfhdkV9Rc5qgeWuU= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-io1-xd2c.google.com (mail-io1-xd2c.google.com [IPv6:2607:f8b0:4864:20::d2c]) by sourceware.org (Postfix) with ESMTPS id 83EA93858C83 for ; Fri, 1 Apr 2022 19:20:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 83EA93858C83 Received: by mail-io1-xd2c.google.com with SMTP id 9so4341898iou.5 for ; Fri, 01 Apr 2022 12:20:01 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=w42ncdUkTPBaBNA7nFShXBqFCSj0GaQZyto0I+eMoLw=; b=UoN8JE75909t8DUmU0c7kiTfWSxnQhjyohB2Gh1rGrOi8H9vQQMJ04bSmbOEAdxkW2 ddeDvlMqjSAB88Loa3cp3l/+jEgivLW3CCFq/ePSxanWHm687+T8E0yx2zfgxZDrwmEq e7oslv6nNuYgzzF7r3pAbxVI7ya2oDgekYxkv7We0UbLiNyRd533aJKp/sq21NSUWA0r xyAarci+fkiQlgYXAxsS0IE1qzlegQ2s4MuSLGnToWSE4CDEe34MRsszAPWaUdkpDwhF L35zS8sHh6PTIpx2pV/r1QD0/CeIIvaIZ4APo/SKP/pWZvwmEVzaR5EAIrTgJYTK8oh+ 0s3w== X-Gm-Message-State: AOAM532qbtM29UUlOACDEFaObRyRnC7Q78f5ed3B8/CqMthoSbQUiOrl bxpJQhDqE08F4H2V86LRwPEBJ8bH/kKhtGPj4PwKKeJiAJ5RUQ== X-Google-Smtp-Source: ABdhPJzHBKFo38E7codUb5rtm8YIFXjVCUZjIir2xga/MA4dBMKKkePoXs3ydLVkWHO9L7wFhM4yxPY4aole02/hQVE= X-Received: by 2002:a02:cce9:0:b0:321:28f9:50c5 with SMTP id l9-20020a02cce9000000b0032128f950c5mr6316635jaq.150.1648840800358; Fri, 01 Apr 2022 12:20:00 -0700 (PDT) MIME-Version: 1.0 Date: Sat, 2 Apr 2022 00:19:47 +0500 Message-ID: Subject: -Wformat-overflow handling for %b and %B directives in C2X standard To: gcc-patches@gcc.gnu.org X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, HTML_MESSAGE, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-Content-Filtered-By: Mailman/MimeDel 2.1.29 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Frolov Daniil via Gcc-patches From: Frolov Daniil Reply-To: Frolov Daniil Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hello, I've noticed that -Wformat-overflow doesn't handle %b and %B directives in the sprintf function. I've added a relevant issue in bugzilla (bug #105129). I attach a patch with a possible solution to the letter. From 2051344e9500651f6e94c44cbc7820715382b957 Mon Sep 17 00:00:00 2001 From: Frolov Daniil Date: Fri, 1 Apr 2022 00:47:03 +0500 Subject: [PATCH] Support %b, %B for -Wformat-overflow (sprintf, snprintf) testsuite: add tests to check -Wformat-overflow on %b. Wformat-overflow1.c is compiled using -std=c2x so warning has to be throwed Wformat-overflow2.c doesn't throw warnings cause c2x std isn't used gcc/ChangeLog: * gimple-ssa-sprintf.cc (check_std_c2x): New function (fmtresult::type_max_digits): add base == 2 handling (tree_digits): add handle for base == 2 (format_integer): now handle %b and %B using base = 2 (parse_directive): add cases to handle %b and %B directives (compute_format_length): add handling for base = 2 gcc/testsuite/ChangeLog: * gcc.dg/Wformat-overflow1.c: New test. (using -std=c2x) * gcc.dg/Wformat-overflow2.c: New test. (-std=c11 no warning) --- gcc/gimple-ssa-sprintf.cc | 42 ++++++++++++++++++++---- gcc/testsuite/gcc.dg/Wformat-overflow1.c | 28 ++++++++++++++++ gcc/testsuite/gcc.dg/Wformat-overflow2.c | 16 +++++++++ 3 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/Wformat-overflow1.c create mode 100644 gcc/testsuite/gcc.dg/Wformat-overflow2.c diff --git a/gcc/gimple-ssa-sprintf.cc b/gcc/gimple-ssa-sprintf.cc index c93f12f90b5..7f68c2b6e51 100644 --- a/gcc/gimple-ssa-sprintf.cc +++ b/gcc/gimple-ssa-sprintf.cc @@ -107,6 +107,15 @@ namespace { static int warn_level; +/* b_overflow_flag depends on the current standart when using gcc */ +static bool b_overflow_flag; + +/* check is current standart version equals C2X*/ +static bool check_std_c2x () +{ + return !strcmp (lang_hooks.name, "GNU C2X"); +} + /* The minimum, maximum, likely, and unlikely maximum number of bytes of output either a formatting function or an individual directive can result in. */ @@ -535,6 +544,8 @@ fmtresult::type_max_digits (tree type, int base) unsigned prec = TYPE_PRECISION (type); switch (base) { + case 2: + return prec; case 8: return (prec + 2) / 3; case 10: @@ -857,11 +868,11 @@ tree_digits (tree x, int base, HOST_WIDE_INT prec, bool plus, bool prefix) /* Adjust a non-zero value for the base prefix, either hexadecimal, or, unless precision has resulted in a leading zero, also octal. */ - if (prefix && absval && (base == 16 || prec <= ndigs)) + if (prefix && absval && (base == 2 || base == 16 || prec <= ndigs)) { if (base == 8) res += 1; - else if (base == 16) + else if (base == 16 || base == 2) /*0x...(0X...) and 0b...(0B...)*/ res += 2; } @@ -1229,6 +1240,10 @@ format_integer (const directive &dir, tree arg, pointer_query &ptr_qry) case 'u': base = 10; break; + case 'b': + case 'B': + base = 2; + break; case 'o': base = 8; break; @@ -1351,10 +1366,10 @@ format_integer (const directive &dir, tree arg, pointer_query &ptr_qry) /* Bump up the counters if WIDTH is greater than LEN. */ res.adjust_for_width_or_precision (dir.width, dirtype, base, - (sign | maybebase) + (base == 16)); + (sign | maybebase) + (base == 2 || base == 16)); /* Bump up the counters again if PRECision is greater still. */ res.adjust_for_width_or_precision (dir.prec, dirtype, base, - (sign | maybebase) + (base == 16)); + (sign | maybebase) + (base == 2 || base == 16)); return res; } @@ -1503,7 +1518,7 @@ format_integer (const directive &dir, tree arg, pointer_query &ptr_qry) if (res.range.min == 1) res.range.likely += base == 8 ? 1 : 2; else if (res.range.min == 2 - && base == 16 + && (base == 16 || base == 2) && (dir.width[0] == 2 || dir.prec[0] == 2)) ++res.range.likely; } @@ -1511,9 +1526,9 @@ format_integer (const directive &dir, tree arg, pointer_query &ptr_qry) res.range.unlikely = res.range.max; res.adjust_for_width_or_precision (dir.width, dirtype, base, - (sign | maybebase) + (base == 16)); + (sign | maybebase) + (base == 2 || base == 16)); res.adjust_for_width_or_precision (dir.prec, dirtype, base, - (sign | maybebase) + (base == 16)); + (sign | maybebase) + (base == 2 || base == 16)); return res; } @@ -3680,6 +3695,8 @@ parse_directive (call_info &info, ++pf; break; } + + switch (target_to_host (*pf)) { @@ -3713,6 +3730,14 @@ parse_directive (call_info &info, case 'X': dir.fmtfunc = format_integer; break; + + case 'b': + case 'B': + if (b_overflow_flag) { + dir.fmtfunc = format_integer; + break; + } + return 0; case 'p': /* The %p output is implementation-defined. It's possible @@ -4038,6 +4063,9 @@ compute_format_length (call_info &info, format_result *res, bool success = true; + /* Check for GNU C2X standart */ + b_overflow_flag = check_std_c2x (); + for (const char *pf = info.fmtstr; ; ++dirno) { directive dir (&info, dirno); diff --git a/gcc/testsuite/gcc.dg/Wformat-overflow1.c b/gcc/testsuite/gcc.dg/Wformat-overflow1.c new file mode 100644 index 00000000000..cf9766fae14 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wformat-overflow1.c @@ -0,0 +1,28 @@ +/* + { dg-do compile } + { dg-options "-Wformat-overflow -std=c2x" } +*/ + +extern int sprintf (char* restrict, const char* restrict, ...); + +void test_warn () { + + int n = __INT_MAX__; + char dst [5] = {0}; + sprintf (dst, "%b", n); /* { dg-warning "-Wformat-overflow" } */ + + sprintf (dst, "%#b", n); /* { dg-warning "-Wformat-overflow" } */ + +} + +void test_no_warn () { + + char dst [5] = {0}; + int n = 8; + sprintf (dst, "%b", n); + + char another_dst [34] = {0}; + n = __INT_MAX__; + sprintf (another_dst, "%#b", n); + +} diff --git a/gcc/testsuite/gcc.dg/Wformat-overflow2.c b/gcc/testsuite/gcc.dg/Wformat-overflow2.c new file mode 100644 index 00000000000..c6b1d9062a6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wformat-overflow2.c @@ -0,0 +1,16 @@ +/* + { dg-do compile } + { dg-options "-Wformat-overflow -std=c11" } +*/ + +extern int sprintf (char* restrict, const char* restrict, ...); + +void test_no_warn () { + + /*There is no reason to throw warning if std < c2x*/ + + char dst [5] = {0}; + int n = 32; + sprintf (dst, "%b", n); + +} -- 2.25.1