Throw Node's TypeError for util.diff of two distinct empty sequences

util.diff([], []) with two arrays read one element past its trace row
while backtracking. Node's myersDiff answers undefined for two empty
sequences, and util.diff's ArrayPrototypeReverse throws "Cannot convert
undefined or null to object"; scr_util_diff now throws the same TypeError
before it allocates the trace.
This commit is contained in:
Chris Tate
2026-10-24 20:19:50 -05:00
parent c41af6c36d
commit 320a97bf3b
2 changed files with 12 additions and 1 deletions
+11
View File
@@ -881,6 +881,17 @@ ScrDyn *scr_util_diff(ScrDyn *actual, ScrDyn *expected) {
scr_throw_error_msg_code(SCR_ERR_RANGE, message, (size_t)n, "ERR_OUT_OF_RANGE");
return NULL;
}
/* Two distinct empty sequences: Node's myersDiff reads past its
* one-element state, finds no end and answers undefined, which the
* ArrayPrototypeReverse of util.diff rejects. The trace below would be read
* out of bounds. */
if (max == 0) {
uc_diff_seq_free(&a);
uc_diff_seq_free(&e);
static const char message[] = "Cannot convert undefined or null to object";
scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
return NULL;
}
size_t width = 2 * max + 1;
int32_t *v = calloc(width, sizeof *v);
int32_t **trace = malloc((max + 1) * sizeof *trace);
+1 -1
View File
@@ -7,7 +7,7 @@ const show = (a, e) => {
try { console.log(JSON.stringify(util.diff(a, e))); } catch (err) { console.log(err.name, err.code, err.message); }
};
show("abc", "abd"); show("kitten", "sitting"); show("", "x"); show("same", "same"); show("", "");
show(["a", "b", "c"], ["a", "c", "d"]); show(["x"], []); show([], ["y", "z"]);
show(["a", "b", "c"], ["a", "c", "d"]); show(["x"], []); show([], ["y", "z"]); show([], []);
const arr = ["p"]; show(arr, arr); show(1, 1); show(1, 2); show("a", 2); show(["a", 1], ["a"]); show(["a"], [, "b"]);
show(null, "x"); show("x", undefined); show("héllo😀", "hello😀"); show({}, "x");
show("the quick brown fox", "the quack brown box");