#include "term/term.h" #include #include #include #include static bool fail_next_realloc; static int malloc_failure_countdown = -1; static bool malloc_was_failed; void *__real_malloc(size_t); void *__wrap_malloc(size_t size) { if (malloc_failure_countdown >= 0) { if (malloc_failure_countdown-- == 0) { malloc_failure_countdown = -1; malloc_was_failed = true; return NULL; } } return __real_malloc(size); } void *__real_realloc(void *, size_t); void *__wrap_realloc(void *p, size_t size) { if (fail_next_realloc) { fail_next_realloc = false; return NULL; } return __real_realloc(p, size); } int main(void) { struct term_options options = { .size = { 8, 3 }, .scrollback = 5 }; struct term *term = term_new(&options); struct term_snapshot *snapshot = term_snapshot_new(); assert(term && snapshot && term_snapshot_update(snapshot, term)); const char accented[] = "e\xcc\x81"; term_feed(term, accented, sizeof(accented) - 1, 0); fail_next_realloc = true; assert(!term_snapshot_update(snapshot, term)); assert(!fail_next_realloc); assert(term_snapshot_view(snapshot)->size.x == 0); assert(term_snapshot_view(snapshot)->size.y == 0); assert(term_snapshot_row(snapshot, 0) == NULL); assert(term_snapshot_update(snapshot, term)); const struct term_cell *row = term_snapshot_row(snapshot, 0); assert(row); uint32_t cps[4]; assert(term_snapshot_cluster(snapshot, row[0].text, cps, 4) == 2); assert(cps[0] == 'e' && cps[1] == 0x301); term_snapshot_free(snapshot); term_free(term); /* More than 256 rows moves both temporary arrays off the stack. */ options.size.y = 300; term = term_new(&options); snapshot = term_snapshot_new(); assert(term && snapshot && term_snapshot_update(snapshot, term)); /* Fail new_keys allocation, then make sure retry fills all rows. */ malloc_was_failed = false; malloc_failure_countdown = 0; assert(!term_snapshot_update(snapshot, term)); assert(malloc_was_failed); assert(term_snapshot_view(snapshot)->size.y == 0); assert(term_snapshot_row(snapshot, 0) == NULL); assert(term_snapshot_update(snapshot, term)); assert(term_snapshot_view(snapshot)->size.y == 300); assert(term_snapshot_row(snapshot, 299)); /* The first malloc is new_keys; fail the following selection-span array. */ malloc_was_failed = false; malloc_failure_countdown = 1; assert(!term_snapshot_update(snapshot, term)); assert(malloc_was_failed); assert(term_snapshot_view(snapshot)->size.y == 0); assert(term_snapshot_row(snapshot, 0) == NULL); assert(term_snapshot_update(snapshot, term)); assert(term_snapshot_view(snapshot)->size.y == 300); assert(term_snapshot_row(snapshot, 299)); term_snapshot_free(snapshot); term_free(term); return 0; }