test_hexdump: test all possible group sizes for overflow
[deliverable/linux.git] / lib / test_hexdump.c
CommitLineData
64d1d77a
AS
1/*
2 * Test cases for lib/hexdump.c module.
3 */
4#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
5
6#include <linux/init.h>
7#include <linux/kernel.h>
8#include <linux/module.h>
9#include <linux/random.h>
10#include <linux/string.h>
11
12static const unsigned char data_b[] = {
13 '\xbe', '\x32', '\xdb', '\x7b', '\x0a', '\x18', '\x93', '\xb2', /* 00 - 07 */
14 '\x70', '\xba', '\xc4', '\x24', '\x7d', '\x83', '\x34', '\x9b', /* 08 - 0f */
15 '\xa6', '\x9c', '\x31', '\xad', '\x9c', '\x0f', '\xac', '\xe9', /* 10 - 17 */
16 '\x4c', '\xd1', '\x19', '\x99', '\x43', '\xb1', '\xaf', '\x0c', /* 18 - 1f */
17};
18
19static const unsigned char data_a[] = ".2.{....p..$}.4...1.....L...C...";
20
c79574ab 21static const char * const test_data_1_le[] __initconst = {
64d1d77a
AS
22 "be", "32", "db", "7b", "0a", "18", "93", "b2",
23 "70", "ba", "c4", "24", "7d", "83", "34", "9b",
24 "a6", "9c", "31", "ad", "9c", "0f", "ac", "e9",
25 "4c", "d1", "19", "99", "43", "b1", "af", "0c",
26};
27
79e23d57 28static const char * const test_data_2_le[] __initconst = {
64d1d77a
AS
29 "32be", "7bdb", "180a", "b293",
30 "ba70", "24c4", "837d", "9b34",
31 "9ca6", "ad31", "0f9c", "e9ac",
32 "d14c", "9919", "b143", "0caf",
33};
34
79e23d57 35static const char * const test_data_4_le[] __initconst = {
64d1d77a
AS
36 "7bdb32be", "b293180a", "24c4ba70", "9b34837d",
37 "ad319ca6", "e9ac0f9c", "9919d14c", "0cafb143",
38};
39
79e23d57 40static const char * const test_data_8_le[] __initconst = {
64d1d77a
AS
41 "b293180a7bdb32be", "9b34837d24c4ba70",
42 "e9ac0f9cad319ca6", "0cafb1439919d14c",
43};
44
3db4a987
AS
45#define FILL_CHAR '#'
46
87977ca6
AS
47static void __init test_hexdump_prepare_test(size_t len, int rowsize,
48 int groupsize, char *test,
49 size_t testlen, bool ascii)
64d1d77a 50{
64d1d77a 51 char *p;
17974c05 52 const char * const *result;
64d1d77a
AS
53 size_t l = len;
54 int gs = groupsize, rs = rowsize;
55 unsigned int i;
56
64d1d77a
AS
57 if (rs != 16 && rs != 32)
58 rs = 16;
59
60 if (l > rs)
61 l = rs;
62
63 if (!is_power_of_2(gs) || gs > 8 || (len % gs != 0))
64 gs = 1;
65
66 if (gs == 8)
67 result = test_data_8_le;
68 else if (gs == 4)
69 result = test_data_4_le;
70 else if (gs == 2)
71 result = test_data_2_le;
72 else
73 result = test_data_1_le;
74
64d1d77a
AS
75 /* hex dump */
76 p = test;
77 for (i = 0; i < l / gs; i++) {
78 const char *q = *result++;
79 size_t amount = strlen(q);
80
81 strncpy(p, q, amount);
3db4a987
AS
82 p += amount;
83
84 *p++ = ' ';
64d1d77a
AS
85 }
86 if (i)
87 p--;
88
89 /* ASCII part */
90 if (ascii) {
3db4a987
AS
91 do {
92 *p++ = ' ';
93 } while (p < test + rs * 2 + rs / gs + 1);
94
64d1d77a
AS
95 strncpy(p, data_a, l);
96 p += l;
97 }
98
99 *p = '\0';
87977ca6
AS
100}
101
102#define TEST_HEXDUMP_BUF_SIZE (32 * 3 + 2 + 32 + 1)
103
104static void __init test_hexdump(size_t len, int rowsize, int groupsize,
105 bool ascii)
106{
107 char test[TEST_HEXDUMP_BUF_SIZE];
108 char real[TEST_HEXDUMP_BUF_SIZE];
109
7047d813 110 memset(real, FILL_CHAR, sizeof(real));
87977ca6
AS
111 hex_dump_to_buffer(data_b, len, rowsize, groupsize, real, sizeof(real),
112 ascii);
113
7047d813 114 memset(test, FILL_CHAR, sizeof(test));
87977ca6
AS
115 test_hexdump_prepare_test(len, rowsize, groupsize, test, sizeof(test),
116 ascii);
64d1d77a 117
7047d813 118 if (memcmp(test, real, TEST_HEXDUMP_BUF_SIZE)) {
64d1d77a
AS
119 pr_err("Len: %zu row: %d group: %d\n", len, rowsize, groupsize);
120 pr_err("Result: '%s'\n", real);
121 pr_err("Expect: '%s'\n", test);
122 }
123}
124
125static void __init test_hexdump_set(int rowsize, bool ascii)
126{
127 size_t d = min_t(size_t, sizeof(data_b), rowsize);
128 size_t len = get_random_int() % d + 1;
129
130 test_hexdump(len, rowsize, 4, ascii);
131 test_hexdump(len, rowsize, 2, ascii);
132 test_hexdump(len, rowsize, 8, ascii);
133 test_hexdump(len, rowsize, 1, ascii);
134}
135
1dacd9dd
AS
136static void __init test_hexdump_overflow(size_t buflen, size_t len,
137 int rowsize, int groupsize,
138 bool ascii)
114fc1af 139{
cc77a719 140 char test[TEST_HEXDUMP_BUF_SIZE];
a3d601fc 141 char buf[TEST_HEXDUMP_BUF_SIZE];
cc77a719
AS
142 int rs = rowsize, gs = groupsize;
143 int ae, he, e, f, r;
114fc1af 144 bool a;
114fc1af 145
3db4a987 146 memset(buf, FILL_CHAR, sizeof(buf));
114fc1af 147
ad27a755
AS
148 r = hex_dump_to_buffer(data_b, len, rs, gs, buf, buflen, ascii);
149
150 /*
151 * Caller must provide the data length multiple of groupsize. The
152 * calculations below are made with that assumption in mind.
153 */
154 ae = rs * 2 /* hex */ + rs / gs /* spaces */ + 1 /* space */ + len /* ascii */;
155 he = (gs * 2 /* hex */ + 1 /* space */) * len / gs - 1 /* no trailing space */;
114fc1af
AS
156
157 if (ascii)
ad27a755 158 e = ae;
114fc1af 159 else
ad27a755 160 e = he;
cc77a719
AS
161
162 f = min_t(int, e + 1, buflen);
163 if (buflen) {
164 test_hexdump_prepare_test(len, rs, gs, test, sizeof(test), ascii);
165 test[f - 1] = '\0';
114fc1af 166 }
cc77a719
AS
167 memset(test + f, FILL_CHAR, sizeof(test) - f);
168
169 a = r == e && !memcmp(test, buf, TEST_HEXDUMP_BUF_SIZE);
170
171 buf[sizeof(buf) - 1] = '\0';
114fc1af
AS
172
173 if (!a) {
cc77a719
AS
174 pr_err("Len: %zu buflen: %zu strlen: %zu\n",
175 len, buflen, strnlen(buf, sizeof(buf)));
176 pr_err("Result: %d '%s'\n", r, buf);
177 pr_err("Expect: %d '%s'\n", e, test);
114fc1af
AS
178 }
179}
180
1dacd9dd
AS
181static void __init test_hexdump_overflow_set(size_t buflen, bool ascii)
182{
183 unsigned int i = 0;
184 int rs = (get_random_int() % 2 + 1) * 16;
185
186 do {
187 int gs = 1 << i;
188 size_t len = get_random_int() % rs + gs;
189
190 test_hexdump_overflow(buflen, rounddown(len, gs), rs, gs, ascii);
191 } while (i++ < 3);
192}
193
64d1d77a
AS
194static int __init test_hexdump_init(void)
195{
196 unsigned int i;
197 int rowsize;
198
199 pr_info("Running tests...\n");
200
201 rowsize = (get_random_int() % 2 + 1) * 16;
202 for (i = 0; i < 16; i++)
203 test_hexdump_set(rowsize, false);
204
205 rowsize = (get_random_int() % 2 + 1) * 16;
206 for (i = 0; i < 16; i++)
207 test_hexdump_set(rowsize, true);
208
a3d601fc 209 for (i = 0; i <= TEST_HEXDUMP_BUF_SIZE; i++)
1dacd9dd 210 test_hexdump_overflow_set(i, false);
114fc1af 211
a3d601fc 212 for (i = 0; i <= TEST_HEXDUMP_BUF_SIZE; i++)
1dacd9dd 213 test_hexdump_overflow_set(i, true);
114fc1af 214
64d1d77a
AS
215 return -EINVAL;
216}
217module_init(test_hexdump_init);
218MODULE_LICENSE("Dual BSD/GPL");
This page took 0.076818 seconds and 5 git commands to generate.