Fixed template literal from producing byte-strings.
Previously, as a side effect of creating a key for the values hash a
byte-string was created. This byte-string was reused internally and
might appear in template literal. As a result a byte-string was
produced as a value for a template literal. Byte-strings are obsolete
and are scheduled for removal because they can cause issues with
internal routines not prepared for them.
Fixed typed-array ctor when source array is changed while iterating.
Previously, the function used optimization for ordinary arrays with no
gaps (so called fast arrays). For a fast array code took elements
directly from internal flat C array. The direct pointer may become
invalid as side-effect of custom valueOf() method for an element.
The fix is to eliminate the micro-optimization which uses direct
pointers.
The problem is similar to the 9578cc729205 (0.7.2) commit.
Previously, while interpreting a user function, njs_vmcode_interpreter()
might return prematurely when an error happens in await instruction.
This is not correct because the current frame has to be unwound (or
exception caught) first.
The fix is to exit through only 5 appropriate exit points to ensure
proper unwinding.
The patch correctly fixes issue reported in 07ef6c1f04f1 (0.7.3).
Dmitry Volyntsev [Thu, 19 May 2022 23:41:08 +0000 (16:41 -0700)]
Fixed redefinition of special props in Object.defineProperty().
Previously, when NJS_PROPERTY_HANDLER property was updated it might be
left in inconsistent state. Namely, prop->type was left unchanged, but
prop->value did not have an expected property handler. As a result
consecutive reference to the property may result in a segment violation.
The fix is to update the prop->type during redefinition.
HTTP: expect escaped URIs in r.internalRedirect().
Similarly to the nginx change in 975d7ab37b39 (1.17.2), we should accept
properly escaped URIs and unescape them as needed, else it is not possible
to handle URIs with question marks.
Fixed Array.prototype.lastIndexOf() with unicode string as "this".
Previously, when lastIndexOf() was called with unicode string as "this"
argument and a negative "fromIndex" argument null-pointer dererence
might occur because njs_string_offset() was called with invalid index
value whereas njs_string_offset() should always be called with valid
index argument.
Fixed aggregation methods of Promise ctor with array-like object.
Previously, while iterating over an array-like object the methods may be
resolved with INVALID values. INVALID value is a special internal type which
should never be visible by ordinary functions.
The fix is to ensure that absent elements are represented by undefined value.
The following methods were fixed Promise.all(), Promise.allSettled(),
Promise.any(), Promise.race().
Fixed Array.prototype.slice() with slow "this" argument.
Previously, when "this" argument was not a fast array, but the "deleted" array
was a fast array, the "deleted" array may be left in uninitialized state if
"this" argument had gaps.
This fix is to ensure that "deleted" is properly initialized.
Dmitry Volyntsev [Mon, 28 Mar 2022 16:22:17 +0000 (16:22 +0000)]
Fixed njs_vmcode_interpreter() when "toString" conversion fails.
Previously, while interpreting a user function, njs_vmcode_interpreter()
might return prematurely when an error happens. This is not correct
because the current frame has to be unwound (or exception caught)
first.
The fix is exit through only 5 appropriate exit points to ensure
proper unwinding.
Dmitry Volyntsev [Mon, 21 Feb 2022 16:53:16 +0000 (16:53 +0000)]
Fixed allocation of large array literals.
Previously, allocation of large array literals may result in
null-pointer dereference. The reason is that njs_array_alloc() may
return a slow array when size is large enough, but the instruction
code assumes that array is always flat.
The fix is to check fast_array flag before accessing array->start.
Dmitry Volyntsev [Mon, 21 Feb 2022 16:52:59 +0000 (16:52 +0000)]
Fixed frame allocation from an awaited frame.
njs_function_frame_save() is used to save the awaited frame when "await"
instruction is encountered. The saving was done as a memcpy() of
existing runtime frame.
njs_function_frame_alloc() is used to alloc a new function frame, this
function tries to use a spare preallocated memory from the previous
frame first. Previously, this function might result in "use-after-free"
when invoked from a restored frame saved with njs_function_frame_save().
Because njs_function_frame_save() left pointers to the spare memory of
the original frame which may be already free when saved frame is
restored.
The fix is to erase fields for the spare memory from the saved frame.
Dmitry Volyntsev [Mon, 21 Feb 2022 16:52:47 +0000 (16:52 +0000)]
Fixed Array.prototype.concat() when "this" is a slow array.
Previously, when the current appended element is fast array the "this"
array was expected to always be a fast array also. This may not be the
case when the previous appended element was not fast thus converting
the "this" array to a slow form.
Previous fix introduced in 2c1382bab643 (0.7.2) was not complete, the
correct fix is to never assume "this" is fast, whereas njs_array_add()
may only be called with fast arrays.
Dmitry Volyntsev [Mon, 21 Feb 2022 14:49:38 +0000 (14:49 +0000)]
Refactoring of user modules importing.
Previously, user modules were compiled as as anonymous functions in a
global scope. This is incorrect, because modules should be compiled
in their own scope.
In addition, this patch introduces HostResolveImportedModule support.
When vm->options.ops->module_loader is provided, a module lookup
and compilation is delegated to this callback.
Dmitry Volyntsev [Mon, 14 Feb 2022 14:10:47 +0000 (14:10 +0000)]
Fixed Function constructor in CLI.
Previously, Function constructor exported its local variables to
vm->variables_hash. vm->variables_hash is used in njs CLI to query
global variables during console input completion. The exporting is
incorrect because it pollutes the global scope.
Dmitry Volyntsev [Mon, 14 Feb 2022 14:10:04 +0000 (14:10 +0000)]
Fixed backtraces while traversing imported user modules.
Previously, njs_builtin_match_native_function(), which is used to build a
backtrace for an exception, assumed that user modules always return
object values, which is not the case. As a result, njs_object_traverse()
may receive incorrect pointer.
Dmitry Volyntsev [Fri, 21 Jan 2022 14:31:30 +0000 (14:31 +0000)]
Fixed recursive async function calls.
Previously, PromiseCapability record was stored (function->context)
directly in function object during a function invocation. This is
not correct, because PromiseCapability record should be linked to
current execution context. As a result, function->context is
overwritten with consecutive recursive calls which results in
use-after-free.
Dmitry Volyntsev [Wed, 19 Jan 2022 14:03:49 +0000 (14:03 +0000)]
Fixed Function.prototype.apply() with slow arrays.
Previously, the function had two issues:
* array->start was referenced without checking for fast array flag
* the created arguments list was not sanity-checked for its length,
which can be very large.
The fix is to remove micro-optimization for arrays and introduce limit
size for arguments list.
Dmitry Volyntsev [Wed, 19 Jan 2022 13:12:09 +0000 (13:12 +0000)]
Fixed type confusion bug while resolving promises.
Previously, the internal function njs_promise_perform_then() which
implements PerformPromiseThen() expects its first argument to always be
a promise instance. This assertion might be invalid because the
functions corresponding to Promise.prototype.then() and
Promise.resolve() incorrectly verified their arguments.
Specifically, the functions recognized their first argument as promise
if it was an object which was an Promise or had Promise object in its
prototype chain. The later condition is not correct because internal
slots are not inherited according to the spec.
Dmitry Volyntsev [Fri, 14 Jan 2022 14:40:27 +0000 (14:40 +0000)]
Fixed Array.prototype.reverse() when array is changed while iterating.
Previously, the flat array may be converted to a slow one as a
side-effect of a custom getter invocation for a proto array object.
The function erroneously assumed that the this array remains flat
while iterating.
The fix is to eliminate the micro-optimization which uses direct
pointers.
Dmitry Volyntsev [Thu, 13 Jan 2022 16:20:58 +0000 (16:20 +0000)]
Fixed Array.prototype.concat() when array is changed while iterating.
Previously, the flat array may be converted to a slow one as a
side-effect of a custom getter invocation for a proto array object.
The function erroneously assumed that the this array remains flat
while iterating.
The fix is to eliminate the micro-optimization which uses direct
pointers.
Dmitry Volyntsev [Thu, 13 Jan 2022 15:59:08 +0000 (15:59 +0000)]
Fixed Array.prototype.slice() when array is changed while iterating.
Previously, the flat array may be converted to a slow one as a
side-effect of a custom getter invocation for a proto array object.
The function erroneously assumed that the this array remains flat
while iterating.
The fix is to eliminate the micro-optimization which uses direct
pointers.
The problem is similar to the previous (9578cc729205) commit.
Dmitry Volyntsev [Wed, 12 Jan 2022 17:59:42 +0000 (17:59 +0000)]
Fixed Array.prototype.join() when array is changed while iterating.
Previously, the function used optimization for ordinary arrays with no
gaps (so called fast arrays). For a fast array code took elements
directly from internal flat C array. The direct pointer may become
invalid as side-effect of custom toString() method for an element.
Specifically, the pointer was passed directly to
njs_value_to_primitive() which attempts to call toString() followed by
valueOf(). When the array size is changed as a side-effect of
toString() and not a string value is returned by toString() the pointer
becomes invalid and is passed to valueOf() which causes use-after-free.
The fix is to eliminate the micro-optimization which uses direct pointers.
Dmitry Volyntsev [Tue, 11 Jan 2022 13:02:33 +0000 (13:02 +0000)]
Fixed fuzzing target bug introduced in 4d4657128baf (0.7.1).
Previously, njs_process_script() took vm pointer from console object,
but after 4d4657128baf the object is not initialized in
LLVMFuzzerTestOneInput().
Dmitry Volyntsev [Fri, 24 Dec 2021 15:48:11 +0000 (15:48 +0000)]
Building regexp backend as an external.
This allows not to build PCRE specific code as a part of libnjs.a thus
supporting nginx builds with flags like --with-pcre=PCRE_DIR. When
--no-pcre configure option is provided external code have to implement
methods declared in njs_regex.h.