summaryrefslogtreecommitdiffhomepage
AgeCommit message (Collapse)Author
2022-02-03lib: fix infinite loop on empty regexp matches in uc_match()Jo-Philipp Wich
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>
2022-02-03lib: fix infinite loop on empty regexp matches in uc_split()Jo-Philipp Wich
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>
2022-02-03vm: ensure consistent trace output between gcc and clang compiled ucodeJo-Philipp Wich
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>
2022-02-03vm: fix leaking function value on call exceptionJo-Philipp Wich
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>
2022-02-03vm: NULL-initialize pointer to make cppcheck happyJo-Philipp Wich
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-02-03source: zero-initialize conversion union to make cppcheck happyJo-Philipp Wich
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-02-03run_tests.sh: change workdir to testcase directory during executionJo-Philipp Wich
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>
2022-02-03run_tests.sh: support placing supplemental testcase filesJo-Philipp Wich
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-02-03run_tests.sh: always treat outputs as text dataJo-Philipp Wich
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-01-30Merge pull request #36 from jow-/bytecode-fixesJo-Philipp Wich
Bytecode fixes
2022-01-29program: rename bytecode load/write functions, track path of executed fileJo-Philipp Wich
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>
2022-01-29lib: fix memory leak in uc_require_ucode()Jo-Philipp Wich
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>
2022-01-26vm: fix NaN strict equality testsJo-Philipp Wich
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>
2022-01-26Merge pull request #35 from jow-/various-fixesJo-Philipp Wich
Various fixes
2022-01-26vallist: uc_number_parse(): parse empty strings as `0`, not `NaN`Jo-Philipp Wich
Fixes: b605dbf ("treewide: rework numeric value handling") Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-01-26vm: fix `null` loose equality/inequality checksJo-Philipp Wich
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>
2022-01-26lib: fix exists() error return valueJo-Philipp Wich
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>
2022-01-26tests: reorganize testcase filesJo-Philipp Wich
- 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>
2022-01-26run_tests.sh: add ability to define environment variables for testcasesJo-Philipp Wich
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-01-26run_tests.sh: fix exitcode evaluationJo-Philipp Wich
The `touch` command result incorrectly shadowed the testcase exit code. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-01-25Merge pull request #34 from jow-/struct-variable-length-string-formatJo-Philipp Wich
2022-01-24struct: implement `*` format, fix invalid memory accessesJo-Philipp Wich
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>
2022-01-23Merge pull request #33 from jow-/lib-format-string-reworkJo-Philipp Wich
lib: rework format string handling
2022-01-23lib: rework format string handlingJo-Philipp Wich
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>
2022-01-20lib: fix %J string formats with precision specifierJo-Philipp Wich
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>
2022-01-18syntax: drop legacy syntax supportJo-Philipp Wich
Drop support for the `local` keyword and `delete` function calls. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-01-18lib: replace usages of vasprintf() with xvasprintf()Jo-Philipp Wich
This avoid triggering -Werror=unused-result compilation failures with certain toolchains. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-01-18Merge pull request #32 from jow-/precompileJo-Philipp Wich
Introduce ucode precompilation support
2022-01-18build: support building without compile capabilitiesJo-Philipp Wich
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>
2022-01-18program: implement support for precompiling source filesJo-Philipp Wich
- 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>
2022-01-18source: refactor source file handlingJo-Philipp Wich
- 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>
2022-01-18compiler, vm: use a program wide constant listJo-Philipp Wich
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>
2022-01-18types: add initial infrastructure for function serializationJo-Philipp Wich
- 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>
2022-01-07Merge pull request #31 from jow-/add-uniqJo-Philipp Wich
lib: implement uniq() function
2022-01-07lib: implement uniq() functionJo-Philipp Wich
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>
2022-01-05Merge pull request #28 from jow-/platform-neutral-doublesJo-Philipp Wich
Platform neutral doubles
2022-01-04vm: optimize string concatenationJo-Philipp Wich
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>
2022-01-04struct: reuse double packing routines from coreJo-Philipp Wich
Use uc_pack_double() and uc_unpack_double() from core to avoid unnecessary code duplication. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-01-04vallist: store double values in a platform neutral mannerJo-Philipp Wich
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>
2022-01-04Merge pull request #30 from jow-/rework-number-handlingJo-Philipp Wich
treewide: rework numeric value handling
2022-01-04treewide: rework numeric value handlingJo-Philipp Wich
- 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>
2022-01-04Merge pull request #29 from jow-/fs-fileno-supportJo-Philipp Wich
fs: implement fdopen(), file.fileno() and proc.fileno()
2022-01-04fs: implement fdopen(), file.fileno() and proc.fileno()Jo-Philipp Wich
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>
2021-12-08Merge pull request #27 from jow-/ubus-defer-supportJo-Philipp Wich
ubus: add support for async requests
2021-12-08ubus: add support for async requestsJo-Philipp Wich
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>
2021-12-08vm: introduce value registryJo-Philipp Wich
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>
2021-12-07treewide: fix "resource" misspellingsJo-Philipp Wich
Fix various misspelling of "resource". This commit changes the exported libucode ABI. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2021-12-07treewide: fix upvalue reference type nameJo-Philipp Wich
No functional changes. Fixes: ff52440 ("treewide: consolidate typedef naming") Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2021-12-06types: consider resource prototypes when marking reachable objectsJo-Philipp Wich
The prevents garbage collecting properties which are stored in resource value prototype objects. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2021-12-05vm: support object property access on resource value typesJo-Philipp Wich
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>