mirror of
https://github.com/tmux/tmux.git
synced 2026-10-11 13:04:22 +00:00
Fix off-by-one buffer growth in sixel_print_add and add regression test.
This commit is contained in:
@@ -823,7 +823,7 @@ static void
|
|||||||
sixel_print_add(char **buf, size_t *len, size_t *used, const char *s,
|
sixel_print_add(char **buf, size_t *len, size_t *used, const char *s,
|
||||||
size_t slen)
|
size_t slen)
|
||||||
{
|
{
|
||||||
while (*used + slen >= *len + 1) {
|
while (*used + slen + 1 > *len) {
|
||||||
*buf = xreallocarray(*buf, 2, *len);
|
*buf = xreallocarray(*buf, 2, *len);
|
||||||
(*len) *= 2;
|
(*len) *= 2;
|
||||||
}
|
}
|
||||||
|
|||||||
72
regress/image-sixel-buffer.c
Normal file
72
regress/image-sixel-buffer.c
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/* Exercise SIXEL output lengths at the encoder's allocation boundary. */
|
||||||
|
|
||||||
|
#undef NDEBUG
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "../tmux.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_IMAGES
|
||||||
|
#include "../image-sixel.c"
|
||||||
|
#include "../xmalloc.c"
|
||||||
|
|
||||||
|
/* Abort if an allocation or formatting check fails. */
|
||||||
|
void
|
||||||
|
fatal(__unused const char *fmt, ...)
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Abort if an allocation or formatting check fails. */
|
||||||
|
void
|
||||||
|
fatalx(__unused const char *fmt, ...)
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Encode lengths below, at and above the initial 8192-byte allocation. */
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
struct sixel_image image = { 0 };
|
||||||
|
u_int colour, width, x;
|
||||||
|
size_t size;
|
||||||
|
char *data;
|
||||||
|
|
||||||
|
colour = (2u << 25) | (100u << 16) | (100u << 8) | 100u;
|
||||||
|
image.sy = 2;
|
||||||
|
image.ncolours = 1;
|
||||||
|
image.used_colours = 1;
|
||||||
|
image.colours = &colour;
|
||||||
|
image.lines = xcalloc(2, sizeof *image.lines);
|
||||||
|
|
||||||
|
/* Headers and controls add 26 bytes to these uncompressed rasters. */
|
||||||
|
for (width = 8165; width <= 8167; width++) {
|
||||||
|
image.sx = width;
|
||||||
|
image.lines[0].sx = width;
|
||||||
|
image.lines[1].sx = width;
|
||||||
|
image.lines[0].pixels = xcalloc(width, sizeof(uint16_t));
|
||||||
|
image.lines[1].pixels = xcalloc(width, sizeof(uint16_t));
|
||||||
|
|
||||||
|
/* Alternate row bits so adjacent columns cannot be compressed. */
|
||||||
|
for (x = 0; x < width; x++)
|
||||||
|
image.lines[x % 2].pixels[x] = 1;
|
||||||
|
data = sixel_print(&image, NULL, &size);
|
||||||
|
assert(data != NULL);
|
||||||
|
assert(size == width + 26);
|
||||||
|
assert(data[size] == '\0');
|
||||||
|
assert(strlen(data) == size);
|
||||||
|
free(data);
|
||||||
|
free(image.lines[0].pixels);
|
||||||
|
free(image.lines[1].pixels);
|
||||||
|
}
|
||||||
|
free(image.lines);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* Skip the encoder check when image support is disabled. */
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
15
regress/image-sixel-buffer.mk
Normal file
15
regress/image-sixel-buffer.mk
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Use the configured compiler and flags for the standalone encoder check.
|
||||||
|
|
||||||
|
.PHONY: sixel-buffer-probe sixel-buffer-test
|
||||||
|
|
||||||
|
sixel-buffer-probe:
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) -fsanitize=address \
|
||||||
|
-o "$(SIXEL_TEST_DIR)/probe" "$(SIXEL_TEST_DIR)/probe.c"
|
||||||
|
|
||||||
|
sixel-buffer-test:
|
||||||
|
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||||
|
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -UNDEBUG \
|
||||||
|
-ffunction-sections -fdata-sections -fsanitize=address \
|
||||||
|
-fno-omit-frame-pointer $(SIXEL_TEST_LDFLAGS) $(LDFLAGS) \
|
||||||
|
-o "$(SIXEL_TEST_DIR)/test" "$(srcdir)/regress/image-sixel-buffer.c" \
|
||||||
|
"$(srcdir)/compat/reallocarray.c"
|
||||||
32
regress/image-sixel-buffer.sh
Normal file
32
regress/image-sixel-buffer.sh
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Catch a trailing NUL written beyond an exactly full SIXEL output buffer.
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
export PATH
|
||||||
|
|
||||||
|
SIXEL_TEST_DIR=$(mktemp -d) || exit 1
|
||||||
|
trap 'rm -rf "$SIXEL_TEST_DIR"' 0 1 15
|
||||||
|
export SIXEL_TEST_DIR
|
||||||
|
ASAN_OPTIONS=detect_leaks=0
|
||||||
|
export ASAN_OPTIONS
|
||||||
|
|
||||||
|
case $(uname -s) in
|
||||||
|
Darwin) SIXEL_TEST_LDFLAGS=-Wl,-dead_strip ;;
|
||||||
|
*) SIXEL_TEST_LDFLAGS=-Wl,--gc-sections ;;
|
||||||
|
esac
|
||||||
|
export SIXEL_TEST_LDFLAGS
|
||||||
|
|
||||||
|
# Skip when the configured compiler or its runtime cannot use ASan.
|
||||||
|
printf 'int main(void) { return 0; }\n' >"$SIXEL_TEST_DIR/probe.c"
|
||||||
|
if ! make -s -C .. -f Makefile -f regress/image-sixel-buffer.mk \
|
||||||
|
sixel-buffer-probe >"$SIXEL_TEST_DIR/probe.log" 2>&1; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if ! "$SIXEL_TEST_DIR/probe" >"$SIXEL_TEST_DIR/probe.log" 2>&1; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
make -s -C .. -f Makefile -f regress/image-sixel-buffer.mk \
|
||||||
|
sixel-buffer-test || exit 1
|
||||||
|
"$SIXEL_TEST_DIR/test" || exit 1
|
||||||
Reference in New Issue
Block a user