diff options
Diffstat (limited to 'lib/hexdump.c')
-rw-r--r-- | lib/hexdump.c | 73 |
1 files changed, 55 insertions, 18 deletions
diff --git a/lib/hexdump.c b/lib/hexdump.c index 4af53f73c7cc..7ea09699855d 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c | |||
@@ -97,22 +97,26 @@ EXPORT_SYMBOL(bin2hex); | |||
97 | * | 97 | * |
98 | * example output buffer: | 98 | * example output buffer: |
99 | * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO | 99 | * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO |
100 | * | ||
101 | * Return: | ||
102 | * The amount of bytes placed in the buffer without terminating NUL. If the | ||
103 | * output was truncated, then the return value is the number of bytes | ||
104 | * (excluding the terminating NUL) which would have been written to the final | ||
105 | * string if enough space had been available. | ||
100 | */ | 106 | */ |
101 | void hex_dump_to_buffer(const void *buf, size_t len, int rowsize, | 107 | int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, |
102 | int groupsize, char *linebuf, size_t linebuflen, | 108 | char *linebuf, size_t linebuflen, bool ascii) |
103 | bool ascii) | ||
104 | { | 109 | { |
105 | const u8 *ptr = buf; | 110 | const u8 *ptr = buf; |
106 | int ngroups; | 111 | int ngroups; |
107 | u8 ch; | 112 | u8 ch; |
108 | int j, lx = 0; | 113 | int j, lx = 0; |
109 | int ascii_column; | 114 | int ascii_column; |
115 | int ret; | ||
110 | 116 | ||
111 | if (rowsize != 16 && rowsize != 32) | 117 | if (rowsize != 16 && rowsize != 32) |
112 | rowsize = 16; | 118 | rowsize = 16; |
113 | 119 | ||
114 | if (!len) | ||
115 | goto nil; | ||
116 | if (len > rowsize) /* limit to one line at a time */ | 120 | if (len > rowsize) /* limit to one line at a time */ |
117 | len = rowsize; | 121 | len = rowsize; |
118 | if (!is_power_of_2(groupsize) || groupsize > 8) | 122 | if (!is_power_of_2(groupsize) || groupsize > 8) |
@@ -122,27 +126,50 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize, | |||
122 | 126 | ||
123 | ngroups = len / groupsize; | 127 | ngroups = len / groupsize; |
124 | ascii_column = rowsize * 2 + rowsize / groupsize + 1; | 128 | ascii_column = rowsize * 2 + rowsize / groupsize + 1; |
129 | |||
130 | if (!linebuflen) | ||
131 | goto overflow1; | ||
132 | |||
133 | if (!len) | ||
134 | goto nil; | ||
135 | |||
125 | if (groupsize == 8) { | 136 | if (groupsize == 8) { |
126 | const u64 *ptr8 = buf; | 137 | const u64 *ptr8 = buf; |
127 | 138 | ||
128 | for (j = 0; j < ngroups; j++) | 139 | for (j = 0; j < ngroups; j++) { |
129 | lx += scnprintf(linebuf + lx, linebuflen - lx, | 140 | ret = snprintf(linebuf + lx, linebuflen - lx, |
130 | "%s%16.16llx", j ? " " : "", | 141 | "%s%16.16llx", j ? " " : "", |
131 | (unsigned long long)*(ptr8 + j)); | 142 | (unsigned long long)*(ptr8 + j)); |
143 | if (ret >= linebuflen - lx) | ||
144 | goto overflow1; | ||
145 | lx += ret; | ||
146 | } | ||
132 | } else if (groupsize == 4) { | 147 | } else if (groupsize == 4) { |
133 | const u32 *ptr4 = buf; | 148 | const u32 *ptr4 = buf; |
134 | 149 | ||
135 | for (j = 0; j < ngroups; j++) | 150 | for (j = 0; j < ngroups; j++) { |
136 | lx += scnprintf(linebuf + lx, linebuflen - lx, | 151 | ret = snprintf(linebuf + lx, linebuflen - lx, |
137 | "%s%8.8x", j ? " " : "", *(ptr4 + j)); | 152 | "%s%8.8x", j ? " " : "", |
153 | *(ptr4 + j)); | ||
154 | if (ret >= linebuflen - lx) | ||
155 | goto overflow1; | ||
156 | lx += ret; | ||
157 | } | ||
138 | } else if (groupsize == 2) { | 158 | } else if (groupsize == 2) { |
139 | const u16 *ptr2 = buf; | 159 | const u16 *ptr2 = buf; |
140 | 160 | ||
141 | for (j = 0; j < ngroups; j++) | 161 | for (j = 0; j < ngroups; j++) { |
142 | lx += scnprintf(linebuf + lx, linebuflen - lx, | 162 | ret = snprintf(linebuf + lx, linebuflen - lx, |
143 | "%s%4.4x", j ? " " : "", *(ptr2 + j)); | 163 | "%s%4.4x", j ? " " : "", |
164 | *(ptr2 + j)); | ||
165 | if (ret >= linebuflen - lx) | ||
166 | goto overflow1; | ||
167 | lx += ret; | ||
168 | } | ||
144 | } else { | 169 | } else { |
145 | for (j = 0; (j < len) && (lx + 3) <= linebuflen; j++) { | 170 | for (j = 0; j < len; j++) { |
171 | if (linebuflen < lx + 3) | ||
172 | goto overflow2; | ||
146 | ch = ptr[j]; | 173 | ch = ptr[j]; |
147 | linebuf[lx++] = hex_asc_hi(ch); | 174 | linebuf[lx++] = hex_asc_hi(ch); |
148 | linebuf[lx++] = hex_asc_lo(ch); | 175 | linebuf[lx++] = hex_asc_lo(ch); |
@@ -154,14 +181,24 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize, | |||
154 | if (!ascii) | 181 | if (!ascii) |
155 | goto nil; | 182 | goto nil; |
156 | 183 | ||
157 | while (lx < (linebuflen - 1) && lx < ascii_column) | 184 | while (lx < ascii_column) { |
185 | if (linebuflen < lx + 2) | ||
186 | goto overflow2; | ||
158 | linebuf[lx++] = ' '; | 187 | linebuf[lx++] = ' '; |
159 | for (j = 0; (j < len) && (lx + 2) < linebuflen; j++) { | 188 | } |
189 | for (j = 0; j < len; j++) { | ||
190 | if (linebuflen < lx + 2) | ||
191 | goto overflow2; | ||
160 | ch = ptr[j]; | 192 | ch = ptr[j]; |
161 | linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.'; | 193 | linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.'; |
162 | } | 194 | } |
163 | nil: | 195 | nil: |
196 | linebuf[lx] = '\0'; | ||
197 | return lx; | ||
198 | overflow2: | ||
164 | linebuf[lx++] = '\0'; | 199 | linebuf[lx++] = '\0'; |
200 | overflow1: | ||
201 | return ascii ? ascii_column + len : (groupsize * 2 + 1) * ngroups - 1; | ||
165 | } | 202 | } |
166 | EXPORT_SYMBOL(hex_dump_to_buffer); | 203 | EXPORT_SYMBOL(hex_dump_to_buffer); |
167 | 204 | ||