diff --git a/src/t_misc.c b/src/t_misc.c
index 59d6260de716d2d78e61db02fe162e8c607e54e4..04ce96c1f6153de2b196be2dbacda55f8e6d9e23 100644
--- a/src/t_misc.c
+++ b/src/t_misc.c
@@ -30,41 +30,50 @@ static void test_tt_registry(void) {
   g_check_cmp_int32(h_get_token_type_number("com.upstandinghackers.test.unkown_token_type"), ==, 0);
 }
 
-// perform a big allocation during parsing to trigger out-of-memory handling
-static HParsedToken *act_big_alloc(const HParseResult *r, void *user) {
-  void *buf = h_arena_malloc(r->arena, 500*1024*1024);
+// test out-of-memory handling with a selectively failing allocator
+static void *fail_alloc(HAllocator *mm__, size_t size) {
+  if(size - 0xdead <= 0x30) // allow for overhead of arena link structure
+    return NULL;
+  return system_allocator.alloc(&system_allocator, size);
+}
+static void *fail_realloc(HAllocator *mm__, void *ptr, size_t size) {
+  return system_allocator.realloc(&system_allocator, ptr, size);
+}
+static void fail_free(HAllocator *mm__, void *ptr) {
+  return system_allocator.free(&system_allocator, ptr);
+}
+static HAllocator fail_allocator = {fail_alloc, fail_realloc, fail_free};
+static HParsedToken *act_oom(const HParseResult *r, void *user) {
+  void *buf = h_arena_malloc(r->arena, 0xdead);
   assert(buf != NULL);
-  g_test_message("Memory allocation was supposed to fail");
-  return NULL;
+  return NULL;  // succeed with null token
 }
 static void test_oom(void) {
-  HParser *p = h_action(h_ch('x'), act_big_alloc, NULL);
+  HParser *p = h_action(h_ch('x'), act_oom, NULL);
     // this should always fail, but never crash
 
-  struct rlimit bak, lim;
-  int i;
-  i = getrlimit(RLIMIT_DATA, &bak);
-  assert(i == 0);
-  lim.rlim_cur = 499*1024*1024;   // never enough
-  if(lim.rlim_cur > bak.rlim_max)
-    lim.rlim_cur = bak.rlim_max;
-  lim.rlim_max = bak.rlim_max;
-  i = setrlimit(RLIMIT_DATA, &lim);
-  assert(i == 0);
-
-  g_check_parse_failed(p, PB_PACKRAT, "x",1);
-  g_check_parse_failed(p, PB_REGULAR, "x",1);
-  g_check_parse_failed(p, PB_LLk, "x",1);
-  g_check_parse_failed(p, PB_LALR, "x",1);
-  g_check_parse_failed(p, PB_GLR, "x",1);
-
-  //g_check_parse_chunks_failed(p, PB_REGULAR, "",0, "x",1);
-  g_check_parse_chunks_failed(p, PB_LLk, "",0, "x",1);
-  g_check_parse_chunks_failed(p, PB_LALR, "",0, "x",1);
-  //g_check_parse_chunks_failed(p, PB_GLR, "",0, "x",1);
+  // sanity-check: parses should succeed with the normal allocator...
+  g_check_parse_ok(p, PB_PACKRAT, "x",1);
+  g_check_parse_ok(p, PB_REGULAR, "x",1);
+  g_check_parse_ok(p, PB_LLk, "x",1);
+  g_check_parse_ok(p, PB_LALR, "x",1);
+  g_check_parse_ok(p, PB_GLR, "x",1);
+  //XXX g_check_parse_chunks_ok(p, PB_REGULAR, "",0, "x",1);
+  g_check_parse_chunks_ok(p, PB_LLk, "",0, "x",1);
+  g_check_parse_chunks_ok(p, PB_LALR, "",0, "x",1);
+  //XXX g_check_parse_chunks_ok(p, PB_GLR, "",0, "x",1);
 
-  i = setrlimit(RLIMIT_DATA, &bak);
-  assert(i == 0);
+  // ...and fail gracefully with the broken one
+  HAllocator *mm__ = &fail_allocator;
+  g_check_parse_failed__m(mm__, p, PB_PACKRAT, "x",1);
+  g_check_parse_failed__m(mm__, p, PB_REGULAR, "x",1);
+  g_check_parse_failed__m(mm__, p, PB_LLk, "x",1);
+  g_check_parse_failed__m(mm__, p, PB_LALR, "x",1);
+  g_check_parse_failed__m(mm__, p, PB_GLR, "x",1);
+  //XXX g_check_parse_chunks_failed__m(mm__, p, PB_REGULAR, "",0, "x",1);
+  g_check_parse_chunks_failed__m(mm__, p, PB_LLk, "",0, "x",1);
+  g_check_parse_chunks_failed__m(mm__, p, PB_LALR, "",0, "x",1);
+  //XXX g_check_parse_chunks_failed__m(mm__, p, PB_GLR, "",0, "x",1);
 }
 
 void register_misc_tests(void) {