efi-boot-shim/include/hexdump.h
Peter Jones 64a18c4ea6 hexdump.h: fix arithmetic error.
When I modified the hexdumper to help debug MokListRT mirroring not
working because of PcdMaxVolatileVariableSize being tiny, I
inadvertently added something that is effectively:

hexdump(..., char *buf, ..., int position)
{
	unsigned long begin = (position % 16);
	unsigned long i;
	...
	for (i = 0; i < begin; i++) {
		...
	}
	...
}

Unfortunately, in c if 0x8 is set in position, that means begin is
0xfffffffffffff8, because signed integer math is horrifying:

include/hexdump.h:99:vhexdumpf() &data[offset]:0x9E77E6BC size-offset:0x14
include/hexdump.h:15:prepare_hex() position:0x9E77E6BC
include/hexdump.h:17:prepare_hex() before:0xFFFFFFFFFFFFFFFC size:0x14
include/hexdump.h:19:prepare_hex() before:0xFFFFFFFFFFFFFFFC after:0x0
include/hexdump.h:21:prepare_hex() buf:0x000000009E77E2BC offset:0 &buf[offset]:0x000000009E77E2BC

Woops.

This could further have been prevented in /some/ cases by simply not
preparing the hexdump buffer when "verbose" is disabled.

This patch makes "pos" be unsigned in all cases, and also checks for
verbose in vhexdumpf() and simply returns if it is 0.

Signed-off-by: Peter Jones <pjones@redhat.com>
2020-10-15 19:17:35 -04:00

144 lines
3.6 KiB
C

#ifndef STATIC_HEXDUMP_H
#define STATIC_HEXDUMP_H
#include <stdint.h>
static inline unsigned long UNUSED
prepare_hex(const void *data, size_t size, char *buf, unsigned int position)
{
char hexchars[] = "0123456789abcdef";
int offset = 0;
unsigned long i;
unsigned long j;
unsigned long ret;
unsigned long before = (position % 16);
unsigned long after = (before+size >= 16) ? 0 : 16 - (before+size);
for (i = 0; i < before; i++) {
buf[offset++] = 'X';
buf[offset++] = 'X';
buf[offset++] = ' ';
if (i == 7)
buf[offset++] = ' ';
}
for (j = 0; j < 16 - after - before; j++) {
uint8_t d = ((uint8_t *)data)[j];
buf[offset++] = hexchars[(d & 0xf0) >> 4];
buf[offset++] = hexchars[(d & 0x0f)];
if (i+j != 15)
buf[offset++] = ' ';
if (i+j == 7)
buf[offset++] = ' ';
}
ret = 16 - after - before;
j += i;
for (i = 0; i < after; i++) {
buf[offset++] = 'X';
buf[offset++] = 'X';
if (i+j != 15)
buf[offset++] = ' ';
if (i+j == 7)
buf[offset++] = ' ';
}
buf[offset] = '\0';
return ret;
}
#define isprint(c) ((c) >= 0x20 && (c) <= 0x7e)
static inline void UNUSED
prepare_text(const void *data, size_t size, char *buf, unsigned int position)
{
int offset = 0;
unsigned long i;
unsigned long j;
unsigned long before = position % 16;
unsigned long after = (before+size > 16) ? 0 : 16 - (before+size);
if (size == 0) {
buf[0] = '\0';
return;
}
for (i = 0; i < before; i++)
buf[offset++] = 'X';
buf[offset++] = '|';
for (j = 0; j < 16 - after - before; j++) {
if (isprint(((uint8_t *)data)[j]))
buf[offset++] = ((uint8_t *)data)[j];
else
buf[offset++] = '.';
}
buf[offset++] = size > 0 ? '|' : 'X';
buf[offset] = '\0';
}
/*
* variadic hexdump formatted
* think of it as: printf("%s%s\n", vformat(fmt, ap), hexdump(data,size));
*/
static inline void UNUSED
vhexdumpf(const char *file, int line, const char *func, const CHAR16 * const fmt, const void *data, unsigned long size, size_t at, va_list ap)
{
unsigned long display_offset = at;
unsigned long offset = 0;
if (verbose == 0)
return;
while (offset < size) {
char hexbuf[49];
char txtbuf[19];
unsigned long sz;
sz = prepare_hex(data+offset, size-offset, hexbuf,
(unsigned long)data+offset);
if (sz == 0)
return;
prepare_text(data+offset, size-offset, txtbuf,
(unsigned long)data+offset);
if (fmt && fmt[0] != 0)
vdprint_(fmt, file, line, func, ap);
dprint_(L"%a:%d:%a() %08lx %a %a\n", file, line, func, display_offset, hexbuf, txtbuf);
display_offset += sz;
offset += sz;
}
}
/*
* hexdump formatted
* think of it as: printf("%s%s", format(fmt, ...), hexdump(data,size)[lineN]);
*/
static inline void UNUSED
hexdumpf(const char *file, int line, const char *func, const CHAR16 * const fmt, const void *data, unsigned long size, size_t at, ...)
{
va_list ap;
va_start(ap, at);
vhexdumpf(file, line, func, fmt, data, size, at, ap);
va_end(ap);
}
static inline void UNUSED
hexdump(const char *file, int line, const char *func, const void *data, unsigned long size)
{
hexdumpf(file, line, func, L"", data, size, (intptr_t)data);
}
static inline void UNUSED
hexdumpat(const char *file, int line, const char *func, const void *data, unsigned long size, size_t at)
{
hexdumpf(file, line, func, L"", data, size, at);
}
#define LogHexdump(data, sz) LogHexdump_(__FILE__, __LINE__, __func__, data, sz)
#define dhexdump(data, sz) hexdump(__FILE__, __LINE__, __func__, data, sz)
#define dhexdumpat(data, sz, at) hexdumpat(__FILE__, __LINE__, __func__, data, sz, at)
#define dhexdumpf(fmt, data, sz, at, ...) hexdumpf(__FILE__, __LINE__, __func__, fmt, data, sz, at, ##__VA_ARGS__)
#endif /* STATIC_HEXDUMP_H */
// vim:fenc=utf-8:tw=75:noet