Age | Commit message (Collapse) | Author |
|
The regular expression `/()/` will match the empty string, causing the
match loop to never advance. Add extra logic to deal with this case.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The regular expression `/()/` will match the empty string, causing the
match loop to never advance. Add extra logic to deal with this case,
similar to the empty separator string logic.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Clang emits code which evaluates function call argument expressions in a
different order, causing `uc_dump_insn()` to receive the instruction pointer
address after decoding the instruction, not before.
Avoid that problem by explicitly caching the pre-decode address in a
temporary variable which is then passed to `uc_dump_insn()`.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The internal uc_vm_call_function() helper may fail in different ways before
the stack frame has been set up, e.g. if the provided function value was not
actually a callable function. In such cases an exception is raised but the
actual function value is leaked since there's not yet a stackframe referring
to it.
Solve the issue by freeing the function value explicitly in these exit cases.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Ensure that that the testcase files are executed within the temporary
testcase work directory to simplify testing relative path resolution.
Also fixup the duplicate resource regression test breaking due to that.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Bytecode fixes
|
|
Extend source objects with a `runpath` field which contains the original
path of the source being executed by the VM.
When instantiating source objects from file paths, the `runpath` will be
set to the `filename`. When instantiating source buffers using
`uc_source_new_buffer()`, the runpath is initially unset.
A new function `uc_source_runpath_set()` can be used to adjust the runtime
path being associated with a source object.
Extend bytecode loading logic to set the source buffer runtime path to the
precompiled bytecode file path being loaded and executed. This is required
for `sourcepath()` and relative paths in `include()` to function correctly
when executing precompiled programs.
Finally rename `uc_program_from_file()` and `uc_program_to_file()` to
`uc_program_load()` and `uc_program_write()` respectively since the load
part now operates on an `uc_source_t` input buffer instead of a plain
`FILE *` handle.
Adjust users of these API functions accordingly.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
We need to release the compiled module function after we executed it in
our VM context.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
A performance shortcut in `ucv_is_equal()` incorrectly led to `NaN === NaN`
being true. Fix the issue by only comparing pointers when the involved
types are not doubles.
Due to fixing `NaN !== NaN`, the `uniq()` function now requires a special
case to treat multiple NaNs equal for the sake of generating an array of
unique values.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Various fixes
|
|
Fixes: b605dbf ("treewide: rework numeric value handling")
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The current implementation incorrectly yielded `true` for `0 == null` but
only `null` must be equal to `null`.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The current implementation incorrectly returned `false` which got treated
as `NULL` instead of a boolean `false` value.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Rename 03_bugs to 04_bugs
- Rename 26_invalid_sparse_array_set to 27_invalid_sparse_array_set
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The `touch` command result incorrectly shadowed the testcase exit code.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
|
|
Implement a new `*` format which acts like `s` on unpack but accepts
input records which are shorter than the specified length, e.g. the
following call will yield "abc" while an equivalent "10s" format would
fail:
unpack("2*", "abc") // [ "ab" ]
unpack("10*", "abc") // [ "abc" ]
unpack("10s", "abc") // null
The `*` format is primarily useful to extract the remainder of a variable
length record without having to encode the specific length of the record
directly into the format string.
When packing records, the `*` format takes at most as many bytes as
specified in the format string repeat count. If the input string is
shorter than the given repeat count, only as many bytes as present in
the input string are taken. A bare `*` without any repeat count will take
all bytes from the given input string:
pack("2*", "abc") // "ab"
pack("10*", "abc") // "abc"
pack("*", "abc") // "abc"
pack("10s", "abc") // "abc\0\0\0\0\0\0\0"
Additionally prevent invalid memory accesses when unpacking a buffer
shorter than the length expected by the format string.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
lib: rework format string handling
|
|
Instead of extracting and forwarding recognized conversion directives
from the user supplied format string, properly parse the format string
into its components and reassemble a canonical representation of the
conversion directive internally before handing it to the libc's sprintf()
implementation.
Also take care of selecting the proper conversion specifiers for signed
and unsigned 64bit integer values to fix broken `%d`, `%i`, `%u`, `%o`,
`%x` and `%X` formats on 32bit systems.
While reworking the format logic, also slightly improve `%s` argument
handling by not duplicate the given value if it already is a string,
which reduces the amount of required heap memory.
Ref: https://bugs.openwrt.org/index.php?do=details&task_id=4234
Ref: https://git.openwrt.org/3d3d03479d5b4a976cf1320d29f4bd4937d5a4ba
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Previous refactoring of the code led to an invalid internal format pettern
being used to output the formatted JSON data.
Fixes: 9041e24 ("lib: fix uninitialized memory access on handling %J string formats")
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Drop support for the `local` keyword and `delete` function calls.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
This avoid triggering -Werror=unused-result compilation failures with
certain toolchains.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Introduce ucode precompilation support
|
|
Introduce a new default enable CMake option "COMPILE_SUPPORT" which
allows to disable source code compilation in the ucode interpreter.
Such an interpreter will only be able to load precompiled ucode files.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Introduce new command line flags `-o` and `-O` to write compiled program
code into the specified output file
- Add support for transparently executing precompiled files, the
lexical analyzing and com,pilation phase is skipped in this case
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Move source object pointer into program entity which is referenced by
each function
- Move lineinfo related routines into source.c and use them from lexer.c
since lineinfo encoding does not belong into the lexical analyzer.
- Implement initial infrastructure for detecting source file type,
this is required later to differentiate between plaintext and
precompiled bytecode files
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Instead of storing constant values per function, maintain a global program
wide list for all constant values within the current compilation unit.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Introduce a new "program" entity which holds the list of functions
created during compilation
- Instead of storing pointers to the in-memory function representation
in the constant list, store the index of the function within the
program's function list
- When loading functions from the constant list, retrieve the function
by index from the program entity
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
lib: implement uniq() function
|
|
The uniq() function allows extracting all unique values from a given input
array in an efficient manner. It is roughly equivalent to the following
ucode idiom:
let seen = {}
let unique = filter(array, item => !seen[item]++);
In contrast to the code above, `uniq()` does not rely on implicit
stringification of item values but performs strict equality tests internally.
If equivalence of stringified results is desired, the following code can
be used:
let unique = uniq(map(array, item => "" + item));
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Platform neutral doubles
|
|
When concatenating strings, avoid allocating three times the required
memory in the worst case. Instead of first allocating the string
representations of the operands followed by the memory for the final
string, allocate a string buffer and print the operands into it. This
will grow the target memory as needed and avoid redundant internal
copies of the involved strings.
Also handle the special where the final string fits into a tagged
pointer and deal with it accordingly.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Use uc_pack_double() and uc_unpack_double() from core to avoid unnecessary
code duplication.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Import the binary64 double packing routines from the struct module and
use them to store numeric double values in a platform agnostic big
endian format.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
treewide: rework numeric value handling
|
|
- Parse integer literals as unsigned numeric values in order to be able
to represent the entire unsigned 64bit value range
- Stop parsing minus-prefixed integer literals as negative numbers but
treat them as separate minus operator followed by a positive integer
instead
- Only store unsigned numeric constants in bytecode
- Rework numeric comparison logic to be able to handle full 64bit
unsigned integers
- If possible, yield unsigned 64 bit results for additions
- Simplify numeric value conversion API
- Compile code with -fwrapv for defined signed overflow semantics
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
fs: implement fdopen(), file.fileno() and proc.fileno()
|
|
Implement support for opening existing file descriptors as well as acquiring
the descriptor number from open process and file handles.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
ubus: add support for async requests
|
|
Introduce a new ubus.defer() method which initiates asynchroneous requests
and invokes the completion callback passed as 4th argument once the reply
is received.
This allows multiplexing mutliple ubus requests with the same ucode VM
context / the same uloop event loop.
In case the ucode context is not running under an active uloop, the ubus
module will spawn uloop itself once the first asynchroneous request is
launched and terminate the loop once all pending requests finished.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Introduce a new, lazily allocated value registry which can be used by C
code to store values which should not be garbage collected.
The registry is a plain ucode object internally and treated as GC root
but not exposed to ucode script code, this allows it to retain references
to values which are otherwise completely unreachable from ucode scripts.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Fix various misspelling of "resource".
This commit changes the exported libucode ABI.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
No functional changes.
Fixes: ff52440 ("treewide: consolidate typedef naming")
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The prevents garbage collecting properties which are stored in resource
value prototype objects.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Allow querying object properties on resource values. A resource value may
have a prototype object set whose properties should be enumerable.
Support that use case in the VM.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|