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 21static const char * const test_data_1_le[] __initconst = { 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 28static const char *test_data_2_le[] __initdata = { 29 "32be", "7bdb", "180a", "b293", 30 "ba70", "24c4", "837d", "9b34", 31 "9ca6", "ad31", "0f9c", "e9ac", 32 "d14c", "9919", "b143", "0caf", 33}; 34 35static const char *test_data_4_le[] __initdata = { 36 "7bdb32be", "b293180a", "24c4ba70", "9b34837d", 37 "ad319ca6", "e9ac0f9c", "9919d14c", "0cafb143", 38}; 39 40static const char *test_data_8_le[] __initdata = { 41 "b293180a7bdb32be", "9b34837d24c4ba70", 42 "e9ac0f9cad319ca6", "0cafb1439919d14c", 43}; 44 45static void __init test_hexdump(size_t len, int rowsize, int groupsize, 46 bool ascii) 47{ 48 char test[32 * 3 + 2 + 32 + 1]; 49 char real[32 * 3 + 2 + 32 + 1]; 50 char *p; 51 const char * const *result; 52 size_t l = len; 53 int gs = groupsize, rs = rowsize; 54 unsigned int i; 55 56 hex_dump_to_buffer(data_b, l, rs, gs, real, sizeof(real), ascii); 57 58 if (rs != 16 && rs != 32) 59 rs = 16; 60 61 if (l > rs) 62 l = rs; 63 64 if (!is_power_of_2(gs) || gs > 8 || (len % gs != 0)) 65 gs = 1; 66 67 if (gs == 8) 68 result = test_data_8_le; 69 else if (gs == 4) 70 result = test_data_4_le; 71 else if (gs == 2) 72 result = test_data_2_le; 73 else 74 result = test_data_1_le; 75 76 memset(test, ' ', sizeof(test)); 77 78 /* hex dump */ 79 p = test; 80 for (i = 0; i < l / gs; i++) { 81 const char *q = *result++; 82 size_t amount = strlen(q); 83 84 strncpy(p, q, amount); 85 p += amount + 1; 86 } 87 if (i) 88 p--; 89 90 /* ASCII part */ 91 if (ascii) { 92 p = test + rs * 2 + rs / gs + 1; 93 strncpy(p, data_a, l); 94 p += l; 95 } 96 97 *p = '\0'; 98 99 if (strcmp(test, real)) { 100 pr_err("Len: %zu row: %d group: %d\n", len, rowsize, groupsize); 101 pr_err("Result: '%s'\n", real); 102 pr_err("Expect: '%s'\n", test); 103 } 104} 105 106static void __init test_hexdump_set(int rowsize, bool ascii) 107{ 108 size_t d = min_t(size_t, sizeof(data_b), rowsize); 109 size_t len = get_random_int() % d + 1; 110 111 test_hexdump(len, rowsize, 4, ascii); 112 test_hexdump(len, rowsize, 2, ascii); 113 test_hexdump(len, rowsize, 8, ascii); 114 test_hexdump(len, rowsize, 1, ascii); 115} 116 117static void __init test_hexdump_overflow(bool ascii) 118{ 119 char buf[56]; 120 const char *t = test_data_1_le[0]; 121 size_t l = get_random_int() % sizeof(buf); 122 bool a; 123 int e, r; 124 125 memset(buf, ' ', sizeof(buf)); 126 127 r = hex_dump_to_buffer(data_b, 1, 16, 1, buf, l, ascii); 128 129 if (ascii) 130 e = 50; 131 else 132 e = 2; 133 buf[e + 2] = '\0'; 134 135 if (!l) { 136 a = r == e && buf[0] == ' '; 137 } else if (l < 3) { 138 a = r == e && buf[0] == '\0'; 139 } else if (l < 4) { 140 a = r == e && !strcmp(buf, t); 141 } else if (ascii) { 142 if (l < 51) 143 a = r == e && buf[l - 1] == '\0' && buf[l - 2] == ' '; 144 else 145 a = r == e && buf[50] == '\0' && buf[49] == '.'; 146 } else { 147 a = r == e && buf[e] == '\0'; 148 } 149 150 if (!a) { 151 pr_err("Len: %zu rc: %u strlen: %zu\n", l, r, strlen(buf)); 152 pr_err("Result: '%s'\n", buf); 153 } 154} 155 156static int __init test_hexdump_init(void) 157{ 158 unsigned int i; 159 int rowsize; 160 161 pr_info("Running tests...\n"); 162 163 rowsize = (get_random_int() % 2 + 1) * 16; 164 for (i = 0; i < 16; i++) 165 test_hexdump_set(rowsize, false); 166 167 rowsize = (get_random_int() % 2 + 1) * 16; 168 for (i = 0; i < 16; i++) 169 test_hexdump_set(rowsize, true); 170 171 for (i = 0; i < 16; i++) 172 test_hexdump_overflow(false); 173 174 for (i = 0; i < 16; i++) 175 test_hexdump_overflow(true); 176 177 return -EINVAL; 178} 179module_init(test_hexdump_init); 180MODULE_LICENSE("Dual BSD/GPL"); 181