scst_main: Terminate trace output for an empty CDB

The saved Cppcheck report warns about the formatter output:

  scst/src/scst_main.c:637: warning: Uninitialized variable: buf
  [uninitvar]

scst_dump_cdb does not write anything when cdb_len is zero, but
scst_trace_cmds prints its stack buffer as a string. Unknown opcode
groups can produce an empty CDB, so termination must not depend on
valid command contents.

Initialize nonempty output buffers and leave zero-capacity buffers
untouched. Add KUnit coverage for empty, ordinary, truncated, one-byte
and zero-size output. Include the new private test header in generated
kernel patches.
This commit is contained in:
Gleb Chesnokov
2026-10-21 13:20:12 +03:00
parent e2243f45f1
commit b74e00e63b
4 changed files with 64 additions and 3 deletions
+1
View File
@@ -315,6 +315,7 @@ scst/src/scst_event.c scst/src/scst_event_priv.h scst/src/scst_no_dlm.c \
scst/src/scst_test.h \
scst/src/scst_event_test.h \
scst/src/scst_dlm_test.h \
scst/src/scst_main_test.h \
scst/src/scst_copy_mgr_test.h"
scst_05_targ="scst/src/scst_targ.c scst/src/scst_local_cmd.c \
scst/src/scst_local_cmd.h \
@@ -8,6 +8,7 @@
#endif
#include "../../../scst_lib_test.h"
#include "../../../scst_main_test.h"
#include "../../../scst_dlm.h"
#include "../../../scst_dlm_test.h"
@@ -198,7 +199,45 @@ static void scst_dlm_directory_error_preserves_membership(struct kunit *test)
}
#endif
static void scst_cdb_trace_bounds(struct kunit *test)
{
static const struct {
unsigned int cdb_len;
size_t capacity;
const char *expected;
} cases[] = {
{ 0, 16, "" },
{ 3, 16, "00 ab ff" },
{ 3, 5, "00 a" },
{ 3, 1, "" },
};
u8 cdb[] = { 0x00, 0xab, 0xff };
struct scst_cmd *cmd;
char buf[18];
unsigned int i;
cmd = kunit_kzalloc(test, sizeof(*cmd), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, cmd);
cmd->cdb = cdb;
for (i = 0; i < ARRAY_SIZE(cases); i++) {
memset(buf, 'x', sizeof(buf));
cmd->cdb_len = cases[i].cdb_len;
KUNIT_EXPECT_PTR_EQ(test, scst_dump_cdb(buf + 1, cases[i].capacity, cmd),
buf + 1);
KUNIT_EXPECT_EQ(test, buf[0], 'x');
KUNIT_EXPECT_EQ(test, buf[cases[i].capacity + 1], 'x');
/* memcmp bounds the check even if the formatter misses the NUL. */
KUNIT_EXPECT_EQ(test, memcmp(buf + 1, cases[i].expected,
strlen(cases[i].expected) + 1), 0);
}
memset(buf, 'x', sizeof(buf));
KUNIT_EXPECT_PTR_EQ(test, scst_dump_cdb(buf + 1, 0, cmd), buf + 1);
KUNIT_EXPECT_EQ(test, buf[1], 'x');
}
static struct kunit_case scst_lib_cases[] = {
KUNIT_CASE(scst_cdb_trace_bounds),
#if (defined(CONFIG_DLM) || defined(CONFIG_DLM_MODULE)) && !defined(CONFIG_SCST_NO_DLM)
KUNIT_CASE(scst_dlm_directory_error_preserves_membership),
#endif
+9 -3
View File
@@ -39,7 +39,7 @@
#include "scst_priv.h"
#include "scst_mem.h"
#include "scst_pres.h"
#include "scst_test.h"
#include "scst_main_test.h"
#undef DEFAULT_SYMBOL_NAMESPACE
#define DEFAULT_SYMBOL_NAMESPACE SCST_NAMESPACE
@@ -626,11 +626,17 @@ char *scst_get_cmd_state_name(char *name, int len, unsigned int state)
return name;
}
static char *scst_dump_cdb(char *buf, int buf_len, struct scst_cmd *cmd)
SCST_KUNIT_VISIBLE
char *scst_dump_cdb(char *buf, size_t buf_len, const struct scst_cmd *cmd)
{
char *p = buf, *end = buf + buf_len;
char *p = buf, *end;
int i;
if (!buf_len)
return buf;
*buf = '\0';
end = buf + buf_len;
for (i = 0; i < cmd->cdb_len && p < end; i++)
p += scnprintf(p, end - p, "%s%02x", i ? " " : "", cmd->cdb[i]);
+15
View File
@@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SCST_MAIN_TEST_H
#define SCST_MAIN_TEST_H
#include "scst_test.h"
#ifdef SCST_KUNIT_ENABLED
#include <linux/types.h>
struct scst_cmd;
char *scst_dump_cdb(char *buf, size_t buf_len, const struct scst_cmd *cmd);
#endif
#endif /* SCST_MAIN_TEST_H */