Skip to content

Commit a174cf0

Browse files
committed
Fix duk_hcompfunc data != NULL assumptions
1 parent 89238b9 commit a174cf0

3 files changed

Lines changed: 42 additions & 28 deletions

File tree

src-input/duk_heap_markandsweep.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -87,18 +87,23 @@ DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
8787
duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_LEXENV(heap, f));
8888
duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_VARENV(heap, f));
8989

90-
tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
91-
tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);
92-
while (tv < tv_end) {
93-
duk__mark_tval(heap, tv);
94-
tv++;
95-
}
90+
if (DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL) {
91+
tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
92+
tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);
93+
while (tv < tv_end) {
94+
duk__mark_tval(heap, tv);
95+
tv++;
96+
}
9697

97-
fn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);
98-
fn_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);
99-
while (fn < fn_end) {
100-
duk__mark_heaphdr(heap, (duk_heaphdr *) *fn);
101-
fn++;
98+
fn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);
99+
fn_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);
100+
while (fn < fn_end) {
101+
duk__mark_heaphdr(heap, (duk_heaphdr *) *fn);
102+
fn++;
103+
}
104+
} else {
105+
/* May happen in some out-of-memory corner cases. */
106+
DUK_D(DUK_DPRINT("duk_hcompfunc 'data' is NULL, skipping marking"));
102107
}
103108
} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
104109
duk_hnatfunc *f = (duk_hnatfunc *) h;

src-input/duk_heap_refcount.c

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -125,23 +125,26 @@ DUK_LOCAL void duk__refcount_finalize_hobject(duk_hthread *thr, duk_hobject *h)
125125
duk_tval *tv, *tv_end;
126126
duk_hobject **funcs, **funcs_end;
127127

128-
DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, f) != NULL); /* compiled functions must be created 'atomically' */
129-
130-
tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, f);
131-
tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, f);
132-
while (tv < tv_end) {
133-
DUK_TVAL_DECREF_NORZ(thr, tv);
134-
tv++;
135-
}
128+
if (DUK_HCOMPFUNC_GET_DATA(thr->heap, f) != NULL) {
129+
tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, f);
130+
tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, f);
131+
while (tv < tv_end) {
132+
DUK_TVAL_DECREF_NORZ(thr, tv);
133+
tv++;
134+
}
136135

137-
funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, f);
138-
funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, f);
139-
while (funcs < funcs_end) {
140-
duk_hobject *h_func;
141-
h_func = *funcs;
142-
DUK_ASSERT(DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_func));
143-
DUK_HCOMPFUNC_DECREF_NORZ(thr, (duk_hcompfunc *) h_func);
144-
funcs++;
136+
funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, f);
137+
funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, f);
138+
while (funcs < funcs_end) {
139+
duk_hobject *h_func;
140+
h_func = *funcs;
141+
DUK_ASSERT(DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_func));
142+
DUK_HCOMPFUNC_DECREF_NORZ(thr, (duk_hcompfunc *) h_func);
143+
funcs++;
144+
}
145+
} else {
146+
/* May happen in some out-of-memory corner cases. */
147+
DUK_D(DUK_DPRINT("duk_hcompfunc 'data' is NULL, skipping decref"));
145148
}
146149

147150
DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_heaphdr *) DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f));

src-input/duk_js_var.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,15 @@ DUK_LOCAL void duk__inc_data_inner_refcounts(duk_hthread *thr, duk_hcompfunc *f)
7474
duk_tval *tv, *tv_end;
7575
duk_hobject **funcs, **funcs_end;
7676

77-
DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, f) != NULL); /* compiled functions must be created 'atomically' */
7877
DUK_UNREF(thr);
7978

79+
/* If function creation fails due to out-of-memory, the data buffer
80+
* pointer may be NULL in some cases. That's actually possible for
81+
* GC code, but shouldn't be possible here because the incomplete
82+
* function will be unwound from the value stack and never instantiated.
83+
*/
84+
DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, f) != NULL);
85+
8086
tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, f);
8187
tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, f);
8288
while (tv < tv_end) {

0 commit comments

Comments
 (0)