Module Name: src
Committed By: rillig
Date: Wed Mar 13 06:48:49 UTC 2024
Modified Files:
src/usr.bin/xlint/lint1: cksnprintb.c
Log Message:
lint: trim down the check for snprintb formats
To generate a diff of this commit:
cvs rdiff -u -r1.10 -r1.11 src/usr.bin/xlint/lint1/cksnprintb.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/usr.bin/xlint/lint1/cksnprintb.c
diff -u src/usr.bin/xlint/lint1/cksnprintb.c:1.10 src/usr.bin/xlint/lint1/cksnprintb.c:1.11
--- src/usr.bin/xlint/lint1/cksnprintb.c:1.10 Sun Mar 10 16:27:16 2024
+++ src/usr.bin/xlint/lint1/cksnprintb.c Wed Mar 13 06:48:49 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: cksnprintb.c,v 1.10 2024/03/10 16:27:16 rillig Exp $ */
+/* $NetBSD: cksnprintb.c,v 1.11 2024/03/13 06:48:49 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.10 2024/03/10 16:27:16 rillig Exp $");
+__RCSID("$NetBSD: cksnprintb.c,v 1.11 2024/03/13 06:48:49 rillig Exp $");
#endif
#include <stdbool.h>
@@ -51,35 +51,10 @@ typedef struct {
quoted_iterator it;
uint64_t field_width;
uint64_t covered;
- unsigned covered_start[64];
- unsigned covered_end[64];
+ const char *covered_start[64];
+ int covered_len[64];
} checker;
-static bool
-match_string_literal(const tnode_t *tn, const buffer **str)
-{
- while (tn->tn_op == CVT)
- tn = tn->u.ops.left;
- return tn->tn_op == ADDR
- && tn->u.ops.left->tn_op == STRING
- && (*str = tn->u.ops.left->u.str_literals, (*str)->data != NULL);
-}
-
-static bool
-match_snprintb_call(const function_call *call,
- const buffer **fmt, const tnode_t **val)
-{
- const char *func;
-
- return call->func->tn_op == ADDR
- && call->func->u.ops.left->tn_op == NAME
- && (func = call->func->u.ops.left->u.sym->s_name, true)
- && ((strcmp(func, "snprintb") == 0 && call->args_len == 4)
- || (strcmp(func, "snprintb_m") == 0 && call->args_len == 5))
- && match_string_literal(call->args[2], fmt)
- && (*val = call->args[3], true);
-}
-
static int
len(quoted_iterator it)
{
@@ -126,52 +101,36 @@ check_hex_escape(const buffer *buf, quot
}
static void
-check_overlap(checker *ck, uint64_t dir_lsb, uint64_t width,
- size_t start, size_t end)
+check_bit(checker *ck, uint64_t dir_lsb, uint64_t width,
+ const char *start, int len)
{
unsigned lsb = (unsigned)(ck->new_style ? dir_lsb : dir_lsb - 1);
if (lsb >= 64 || width == 0 || width > 64)
return;
uint64_t field_mask = value_bits((unsigned)width) << lsb;
- uint64_t overlap = ck->covered & field_mask;
- if (overlap == 0)
- goto update_covered;
-
for (unsigned i = lsb; i < 64; i++) {
- if (!(overlap & bit(i)))
- continue;
- /* '%.*s' overlaps earlier '%.*s' on bit %u */
- warning(376,
- (int)(end - start), ck->fmt->data + start,
- (int)(ck->covered_end[i] - ck->covered_start[i]),
- ck->fmt->data + ck->covered_start[i],
- ck->new_style ? i : i + 1);
- break;
+ if (ck->covered & field_mask & bit(i)) {
+ /* '%.*s' overlaps earlier '%.*s' on bit %u */
+ warning(376,
+ len, start, ck->covered_len[i],
+ ck->covered_start[i],
+ ck->new_style ? i : i + 1);
+ break;
+ }
}
-update_covered:
ck->covered |= field_mask;
for (unsigned i = lsb; i < 64; i++) {
if (field_mask & bit(i)) {
- ck->covered_start[i] = (unsigned)start;
- ck->covered_end[i] = (unsigned)end;
+ ck->covered_start[i] = start;
+ ck->covered_len[i] = len;
}
}
-}
-
-static void
-check_reachable(checker *ck, uint64_t dir_lsb, uint64_t width,
- size_t start, size_t end)
-{
- unsigned lsb = (unsigned)(ck->new_style ? dir_lsb : dir_lsb - 1);
- if (lsb >= 64 || width == 0 || width > 64)
- return;
- uint64_t field_mask = value_bits((unsigned)width) << lsb;
if (!(possible_bits(ck->value) & field_mask))
/* directive '%.*s' is unreachable by input value */
- warning(378, (int)(end - start), ck->fmt->data + start);
+ warning(378, len, start);
}
static bool
@@ -266,45 +225,37 @@ check_directive(checker *ck)
check_hex_escape(fmt, bit);
if (has_width)
check_hex_escape(fmt, width);
- if (has_bit && bit.octal_digits == 0 && bit.hex_digits == 0) {
+ if (has_bit && bit.octal_digits == 0 && bit.hex_digits == 0)
/* bit position '%.*s' in '%.*s' should be escaped as ... */
warning(369, len(bit), start(bit, fmt),
range(dir, *it), start(dir, fmt));
- }
- if (has_width && width.octal_digits == 0 && width.hex_digits == 0) {
+ if (has_width && width.octal_digits == 0 && width.hex_digits == 0)
/* field width '%.*s' in '%.*s' should be escaped as ... */
warning(370, len(width), start(width, fmt),
range(dir, *it), start(dir, fmt));
- }
- if (has_bit && (new_style ? bit.value > 63 : bit.value - 1 > 31)) {
+ if (has_bit && (new_style ? bit.value > 63 : bit.value - 1 > 31))
/* bit position '%.*s' (%ju) in '%.*s' out of range %u..%u */
warning(371,
len(bit), start(bit, fmt), val(bit),
range(dir, *it), start(dir, fmt),
new_style ? 0 : 1, new_style ? 63 : 32);
- }
- if (has_width && width.value > 64) {
+ if (has_width && width.value > 64)
/* field width '%.*s' (%ju) in '%.*s' out of range 0..64 */
warning(372,
len(width), start(width, fmt), val(width),
range(dir, *it), start(dir, fmt));
- }
- if (has_width && bit.value + width.value > 64) {
+ if (has_width && bit.value + width.value > 64)
/* bit field end %ju in '%.*s' out of range 0..64 */
warning(373, val(bit) + val(width),
range(dir, *it), start(dir, fmt));
- }
if (has_cmp && ck->field_width > 0 && ck->field_width < 64
- && cmp.value & ~value_bits((unsigned)ck->field_width)) {
+ && 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));
- }
- if (has_bit) {
- uint64_t w = has_width ? width.value : 1;
- check_overlap(ck, bit.value, w, dir.start, it->end);
- check_reachable(ck, bit.value, w, dir.start, it->end);
- }
+ if (has_bit)
+ check_bit(ck, bit.value, has_width ? width.value : 1,
+ ck->fmt->data + dir.start, (int)(it->end - dir.start));
if (needs_descr && !seen_descr)
/* empty description in '%.*s' */
warning(367, range(dir, *it), start(dir, fmt));
@@ -320,9 +271,22 @@ check_directive(checker *ck)
void
check_snprintb(const tnode_t *expr)
{
+ const function_call *call = expr->u.call;
+ const char *name;
const buffer *fmt;
const tnode_t *value;
- if (!match_snprintb_call(expr->u.call, &fmt, &value))
+
+ if (!(call->func->tn_op == ADDR
+ && call->func->u.ops.left->tn_op == NAME
+ && (name = call->func->u.ops.left->u.sym->s_name, true)
+ && ((strcmp(name, "snprintb") == 0 && call->args_len == 4)
+ || (strcmp(name, "snprintb_m") == 0 && call->args_len == 5))
+ && call->args[2]->tn_op == CVT
+ && call->args[2]->u.ops.left->tn_op == ADDR
+ && call->args[2]->u.ops.left->u.ops.left->tn_op == STRING
+ && (fmt = call->args[2]->u.ops.left->u.ops.left->u.str_literals,
+ fmt->data != NULL)
+ && (value = call->args[3], true)))
return;
checker ck = {