Open Markakd opened 1 year ago
https://github.com/nginx/njs/issues/444 is a similar case. The code is like the following:
njs_int_t
njs_value_to_primitive(njs_vm_t *vm, njs_value_t *dst, njs_value_t *value,
njs_uint_t hint)
{
...
for ( ;; ) {
ret = NJS_ERROR;
if (njs_is_object(value) && tries < 2) { // UAF access here inside the loop, value is the dangling pointer after free
hint ^= tries++;
lhq.key_hash = hashes[hint];
lhq.key = names[hint];
ret = njs_object_property(vm, value, &lhq, &method);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
if (njs_is_function(&method)) {
// value is freed inside this function
ret = njs_function_apply(vm, njs_function(&method), value, 1,
&retval);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
if (njs_is_primitive(&retval)) {
break;
}
}
/* Try the second method. */
continue;
}
njs_type_error(vm, "Cannot convert object to primitive value");
return ret;
}
}
An example provided by @kitaharazy, since
char *b = src + 0x40;
is very likely to be optimized into register, there will be no escape, resulting in the fn of UAF.