Module Name: src Committed By: rillig Date: Sun Mar 3 10:27:18 UTC 2024
Modified Files: src/tests/usr.bin/xlint/lint1: msg_363.c msg_364.c msg_365.c msg_366.c msg_367.c msg_374.c msg_377.c src/usr.bin/xlint/lint1: cksnprintb.c err.c Log Message: lint: fix warning about "empty" single-letter snprintb descriptions To generate a diff of this commit: cvs rdiff -u -r1.1 -r1.2 src/tests/usr.bin/xlint/lint1/msg_363.c \ src/tests/usr.bin/xlint/lint1/msg_364.c \ src/tests/usr.bin/xlint/lint1/msg_365.c \ src/tests/usr.bin/xlint/lint1/msg_367.c \ src/tests/usr.bin/xlint/lint1/msg_377.c cvs rdiff -u -r1.2 -r1.3 src/tests/usr.bin/xlint/lint1/msg_366.c \ src/tests/usr.bin/xlint/lint1/msg_374.c cvs rdiff -u -r1.4 -r1.5 src/usr.bin/xlint/lint1/cksnprintb.c cvs rdiff -u -r1.229 -r1.230 src/usr.bin/xlint/lint1/err.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/usr.bin/xlint/lint1/msg_363.c diff -u src/tests/usr.bin/xlint/lint1/msg_363.c:1.1 src/tests/usr.bin/xlint/lint1/msg_363.c:1.2 --- src/tests/usr.bin/xlint/lint1/msg_363.c:1.1 Fri Mar 1 19:39:28 2024 +++ src/tests/usr.bin/xlint/lint1/msg_363.c Sun Mar 3 10:27:18 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: msg_363.c,v 1.1 2024/03/01 19:39:28 rillig Exp $ */ +/* $NetBSD: msg_363.c,v 1.2 2024/03/03 10:27:18 rillig Exp $ */ # 3 "msg_363.c" // Test for message: non-printing character '%.*s' in description '%.*s' [363] @@ -33,7 +33,7 @@ old_style_description(unsigned u32) /* expect+7: warning: bit position '\000' (0) in '\000print' out of range 1..32 [371] */ /* expect+6: warning: old-style format contains '\0' [362] */ /* expect+5: warning: bit position '\n' in '\nable' should be escaped as octal or hex [369] */ - /* expect+4: warning: empty description in '\0' [367] */ + /* expect+4: warning: redundant '\0' at the end of the format [377] */ snprintb(buf, sizeof(buf), "\020" "\001non\000print\nable\0", Index: src/tests/usr.bin/xlint/lint1/msg_364.c diff -u src/tests/usr.bin/xlint/lint1/msg_364.c:1.1 src/tests/usr.bin/xlint/lint1/msg_364.c:1.2 --- src/tests/usr.bin/xlint/lint1/msg_364.c:1.1 Fri Mar 1 19:39:28 2024 +++ src/tests/usr.bin/xlint/lint1/msg_364.c Sun Mar 3 10:27:18 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: msg_364.c,v 1.1 2024/03/01 19:39:28 rillig Exp $ */ +/* $NetBSD: msg_364.c,v 1.2 2024/03/03 10:27:18 rillig Exp $ */ # 3 "msg_364.c" // Test for message: missing bit position after '%.*s' [364] @@ -26,6 +26,7 @@ example(unsigned u32) "b", u32); + /* expect+5: warning: empty description in 'b\007' [367] */ /* expect+4: warning: missing '\0' at the end of 'b\007' [366] */ snprintb(buf, sizeof(buf), "\177\020" Index: src/tests/usr.bin/xlint/lint1/msg_365.c diff -u src/tests/usr.bin/xlint/lint1/msg_365.c:1.1 src/tests/usr.bin/xlint/lint1/msg_365.c:1.2 --- src/tests/usr.bin/xlint/lint1/msg_365.c:1.1 Fri Mar 1 19:39:28 2024 +++ src/tests/usr.bin/xlint/lint1/msg_365.c Sun Mar 3 10:27:18 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: msg_365.c,v 1.1 2024/03/01 19:39:28 rillig Exp $ */ +/* $NetBSD: msg_365.c,v 1.2 2024/03/03 10:27:18 rillig Exp $ */ # 3 "msg_365.c" // Test for message: missing field width after '%.*s' [365] @@ -25,6 +25,7 @@ example(unsigned u32) "f\000", u32); + /* expect+5: warning: empty description in 'f\007\010' [367] */ /* expect+4: warning: missing '\0' at the end of 'f\007\010' [366] */ snprintb(buf, sizeof(buf), "\177\020" Index: src/tests/usr.bin/xlint/lint1/msg_367.c diff -u src/tests/usr.bin/xlint/lint1/msg_367.c:1.1 src/tests/usr.bin/xlint/lint1/msg_367.c:1.2 --- src/tests/usr.bin/xlint/lint1/msg_367.c:1.1 Fri Mar 1 19:39:28 2024 +++ src/tests/usr.bin/xlint/lint1/msg_367.c Sun Mar 3 10:27:18 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: msg_367.c,v 1.1 2024/03/01 19:39:28 rillig Exp $ */ +/* $NetBSD: msg_367.c,v 1.2 2024/03/03 10:27:18 rillig Exp $ */ # 3 "msg_367.c" // Test for message: empty description in '%.*s' [367] @@ -18,7 +18,46 @@ typedef unsigned long long uint64_t; int snprintb(char*, size_t, const char*, uint64_t); void -example(unsigned u32) +old_style(unsigned u32) +{ + char buf[64]; + + /* expect+10: warning: empty description in '\001' [367] */ + /* expect+9: warning: empty description in '\002' [367] */ + /* expect+8: warning: empty description in '\003' [367] */ + /* expect+7: warning: empty description in '\004' [367] */ + snprintb(buf, sizeof(buf), + "\020" + "\001" + "\002" + "\003" + "\004", + u32); + + /* expect+10: warning: empty description in '\001' [367] */ + /* expect+9: warning: empty description in '\002' [367] */ + /* expect+8: warning: empty description in '\003' [367] */ + /* expect+7: warning: empty description in '\004' [367] */ + snprintb(buf, sizeof(buf), + "\020" + "\001" "" "" + "\002" "" "" + "\003" "" "" + "\004" "" "", + u32); + + // Single-letter descriptions are not empty. + snprintb(buf, sizeof(buf), + "\020" + "\001a" + "\002b" + "\003c" + "\004d", + u32); +} + +void +new_style(uint64_t u64) { char buf[64]; @@ -26,37 +65,55 @@ example(unsigned u32) snprintb(buf, sizeof(buf), "\177\020" "b\000\0", - u32); + u64); /* expect+4: warning: empty description in 'f\000\010\0' [367] */ snprintb(buf, sizeof(buf), "\177\020" "f\000\010\0", - u32); + u64); // No warning, as 'F' does not take a description. // If there were a description, it would simply be skipped. snprintb(buf, sizeof(buf), "\177\020" "F\000\010\0", - u32); + u64); /* expect+4: warning: empty description in '=\000\0' [367] */ snprintb(buf, sizeof(buf), "\177\020" "=\000\0", - u32); + u64); /* expect+4: warning: empty description in ':\000\0' [367] */ snprintb(buf, sizeof(buf), "\177\020" ":\000\0", - u32); + u64); /* expect+4: warning: empty description in '*\0' [367] */ snprintb(buf, sizeof(buf), "\177\020" "*\0", - u32); + u64); + // Single-letter descriptions are not empty. + snprintb(buf, sizeof(buf), + "\177\020" + "b\000b\0" + "f\001\001f\0" + "F\002\002F\0" + "=\000z\0" + ":\001o\0" + "*d\0", + u64 >> 1); + + /* expect+6: warning: empty description in 'b\001""""""\0' [367] */ + /* expect+5: warning: empty description in 'b\003""""""\0' [367] */ + snprintb(buf, sizeof(buf), + "\177\020" + "b\001" "" "" "\0" + "b\003" "" "" "\0", + u64); } Index: src/tests/usr.bin/xlint/lint1/msg_377.c diff -u src/tests/usr.bin/xlint/lint1/msg_377.c:1.1 src/tests/usr.bin/xlint/lint1/msg_377.c:1.2 --- src/tests/usr.bin/xlint/lint1/msg_377.c:1.1 Sun Mar 3 00:50:41 2024 +++ src/tests/usr.bin/xlint/lint1/msg_377.c Sun Mar 3 10:27:18 2024 @@ -1,12 +1,14 @@ -/* $NetBSD: msg_377.c,v 1.1 2024/03/03 00:50:41 rillig Exp $ */ +/* $NetBSD: msg_377.c,v 1.2 2024/03/03 10:27:18 rillig Exp $ */ # 3 "msg_377.c" -// Test for message: redundant '\0' at the end of new-style format [377] +// Test for message: redundant '\0' at the end of the format [377] /* - * Each directive in the new-style format ends with a '\0'. The final '\0' - * that ends the whole format is provided implicitly by the compiler as part - * of the string literal. + * Each directive in the new-style format ends with a '\0' that needs to be + * spelled out. + * + * In both old-style and new-style formats, the '\0' that ends the whole + * format is provided by the compiler as part of the string literal. */ /* lint1-extra-flags: -X 351 */ @@ -21,15 +23,18 @@ example(unsigned u32, uint64_t u64) { char buf[64]; - /* expect+6: warning: old-style format contains '\0' [362] */ - /* expect+5: warning: empty description in '\0' [367] */ + /* expect+9: warning: old-style format contains '\0' [362] */ + /* expect+8: warning: old-style format contains '\0' [362] */ + /* expect+7: warning: bit position '\000' (0) in '\000out-of-range' out of range 1..32 [371] */ + /* expect+6: warning: redundant '\0' at the end of the format [377] */ snprintb(buf, sizeof(buf), "\020" "\005bit" + "\000out-of-range" "\0", u32); - /* expect+5: warning: redundant '\0' at the end of new-style format [377] */ + /* expect+5: warning: redundant '\0' at the end of the format [377] */ snprintb(buf, sizeof(buf), "\177\020" "b\005bit\0" Index: src/tests/usr.bin/xlint/lint1/msg_366.c diff -u src/tests/usr.bin/xlint/lint1/msg_366.c:1.2 src/tests/usr.bin/xlint/lint1/msg_366.c:1.3 --- src/tests/usr.bin/xlint/lint1/msg_366.c:1.2 Sun Mar 3 00:50:41 2024 +++ src/tests/usr.bin/xlint/lint1/msg_366.c Sun Mar 3 10:27:18 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: msg_366.c,v 1.2 2024/03/03 00:50:41 rillig Exp $ */ +/* $NetBSD: msg_366.c,v 1.3 2024/03/03 10:27:18 rillig Exp $ */ # 3 "msg_366.c" // Test for message: missing '\0' at the end of '%.*s' [366] @@ -24,18 +24,20 @@ example(unsigned u32) { char buf[64]; - /* expect+4: warning: redundant '\0' at the end of new-style format [377] */ + /* expect+4: warning: redundant '\0' at the end of the format [377] */ snprintb(buf, sizeof(buf), "\177\020" "\0", u32); + /* expect+5: warning: empty description in 'b\007' [367] */ /* expect+4: warning: missing '\0' at the end of 'b\007' [366] */ snprintb(buf, sizeof(buf), "\177\020" "b\007", u32); + /* expect+5: warning: empty description in 'f\007\000' [367] */ /* expect+4: warning: missing '\0' at the end of 'f\007\000' [366] */ snprintb(buf, sizeof(buf), "\177\020" Index: src/tests/usr.bin/xlint/lint1/msg_374.c diff -u src/tests/usr.bin/xlint/lint1/msg_374.c:1.2 src/tests/usr.bin/xlint/lint1/msg_374.c:1.3 --- src/tests/usr.bin/xlint/lint1/msg_374.c:1.2 Sun Mar 3 00:50:41 2024 +++ src/tests/usr.bin/xlint/lint1/msg_374.c Sun Mar 3 10:27:18 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: msg_374.c,v 1.2 2024/03/03 00:50:41 rillig Exp $ */ +/* $NetBSD: msg_374.c,v 1.3 2024/03/03 10:27:18 rillig Exp $ */ # 3 "msg_374.c" // Test for message: unknown directive '%.*s' [374] @@ -32,7 +32,7 @@ example(uint64_t u64) "\00012345\0", u64); - /* expect+5: warning: redundant '\0' at the end of new-style format [377] */ + /* expect+5: warning: redundant '\0' at the end of the format [377] */ snprintb(buf, sizeof(buf), "\177\020" "b\00012345\0" Index: src/usr.bin/xlint/lint1/cksnprintb.c diff -u src/usr.bin/xlint/lint1/cksnprintb.c:1.4 src/usr.bin/xlint/lint1/cksnprintb.c:1.5 --- src/usr.bin/xlint/lint1/cksnprintb.c:1.4 Sun Mar 3 00:50:41 2024 +++ src/usr.bin/xlint/lint1/cksnprintb.c Sun Mar 3 10:27:18 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: cksnprintb.c,v 1.4 2024/03/03 00:50:41 rillig Exp $ */ +/* $NetBSD: cksnprintb.c,v 1.5 2024/03/03 10:27:18 rillig Exp $ */ /*- * Copyright (c) 2024 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: cksnprintb.c,v 1.4 2024/03/03 00:50:41 rillig Exp $"); +__RCSID("$NetBSD: cksnprintb.c,v 1.5 2024/03/03 10:27:18 rillig Exp $"); #endif #include <stdbool.h> @@ -180,6 +180,40 @@ check_reachable(checker *ck, uint64_t di } } +static void +parse_description(const checker *ck, quoted_iterator *it, + bool *seen_null, bool *descr_empty) +{ + bool new_style = ck->new_style; + + quoted_iterator first = *it; + (void)quoted_next(ck->fmt, &first); + size_t descr_start = first.start, descr_end = descr_start; + + for (quoted_iterator peek = *it; quoted_next(ck->fmt, &peek);) { + if (new_style && peek.value == 0) { + *seen_null = true; + *it = peek; + break; + } + if (!new_style && peek.value == 0) + /* old-style format contains '\0' */ + warning(362); + if (!new_style && peek.value <= 32) + break; + *it = peek; + descr_end = peek.i; + if (peek.escaped && !isprint((unsigned char)peek.value)) { + /* non-printing character '%.*s' in description ... */ + warning(363, + len(*it), start(*it, ck->fmt), + (int)(descr_end - descr_start), + ck->fmt->data + descr_start); + } + } + *descr_empty = descr_start == descr_end; +} + static bool check_directive(const buffer *fmt, quoted_iterator *it, bool new_style, checker *ck) @@ -218,16 +252,11 @@ check_directive(const buffer *fmt, quote quoted_iterator cmp = *it; bool has_default = new_style && dir.value == '*'; - if (has_default && !quoted_next(fmt, it)) { - /* missing '\0' at the end of '%.*s' */ - warning(366, range(dir, *it), start(dir, fmt)); - return false; - } - if (new_style && dir.value == '\0') { + if (dir.value == '\0') { quoted_iterator end = *it; if (!quoted_next(fmt, &end)) { - /* redundant '\0' at the end of new-style format */ + /* redundant '\0' at the end of the format */ warning(377); return false; } @@ -239,44 +268,9 @@ check_directive(const buffer *fmt, quote return false; } - if (!quoted_next(fmt, it)) { - if (new_style && dir.value != '*') - /* missing '\0' at the end of '%.*s' */ - warning(366, range(dir, *it), start(dir, fmt)); - else - /* empty description in '%.*s' */ - warning(367, range(dir, *it), start(dir, fmt)); - return false; - } - quoted_iterator descr = *it; - - quoted_iterator prev = *it; - for (;;) { - if (new_style && it->value == 0) - break; - if (!new_style && it->value == 0) - /* old-style format contains '\0' */ - warning(362); - if (!new_style && it->value <= 32) { - *it = prev; - break; - } - if (it->escaped && !isprint((unsigned char)it->value)) { - /* non-printing character '%.*s' in description ... */ - warning(363, - len(*it), start(*it, fmt), - range(descr, *it), start(descr, fmt)); - } - prev = *it; - if (!quoted_next(fmt, it)) { - if (new_style) { - /* missing '\0' at the end of '%.*s' */ - warning(366, range(dir, prev), - start(dir, fmt)); - } - break; - } - } + bool needs_descr = !(new_style && dir.value == 'F'); + bool seen_null = false, descr_empty = false; + parse_description(ck, it, &seen_null, &descr_empty); if (has_bit) check_hex_escape(fmt, bit); @@ -311,8 +305,8 @@ check_directive(const buffer *fmt, quote warning(373, val(bit) + val(width), range(dir, *it), start(dir, fmt)); } - if (has_cmp && ck->field_width < 64 - && cmp.value & ~(uint64_t)0 << ck->field_width) { + if (has_cmp && ck->field_width > 0 && ck->field_width < 64 + && cmp.value & ~value_bits((unsigned)ck->field_width)) { /* comparison value '%.*s' (%ju) exceeds maximum field ... */ warning(375, len(cmp), start(cmp, fmt), val(cmp), (uintmax_t)value_bits((unsigned)ck->field_width)); @@ -325,10 +319,14 @@ check_directive(const buffer *fmt, quote uint64_t w = has_width ? width.value : 1; check_reachable(ck, bit.value, w, dir.start, it->i); } - if (descr.i == prev.i && dir.value != 'F') { + if (needs_descr && descr_empty) { /* empty description in '%.*s' */ warning(367, range(dir, *it), start(dir, fmt)); } + if (new_style && !seen_null) { + /* missing '\0' at the end of '%.*s' */ + warning(366, range(dir, *it), start(dir, fmt)); + } if (has_width) ck->field_width = width.value; Index: src/usr.bin/xlint/lint1/err.c diff -u src/usr.bin/xlint/lint1/err.c:1.229 src/usr.bin/xlint/lint1/err.c:1.230 --- src/usr.bin/xlint/lint1/err.c:1.229 Sun Mar 3 00:50:41 2024 +++ src/usr.bin/xlint/lint1/err.c Sun Mar 3 10:27:18 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: err.c,v 1.229 2024/03/03 00:50:41 rillig Exp $ */ +/* $NetBSD: err.c,v 1.230 2024/03/03 10:27:18 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,7 +37,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: err.c,v 1.229 2024/03/03 00:50:41 rillig Exp $"); +__RCSID("$NetBSD: err.c,v 1.230 2024/03/03 10:27:18 rillig Exp $"); #endif #include <limits.h> @@ -432,7 +432,7 @@ static const char *const msgs[] = { "unknown directive '%.*s'", // 374 "comparison value '%.*s' (%ju) exceeds maximum field value %ju", // 375 "'%.*s' overlaps earlier '%.*s' on bit %u", // 376 - "redundant '\\0' at the end of new-style format", // 377 + "redundant '\\0' at the end of the format", // 377 "directive '%.*s' is unreachable by input value", // 378 };