Age | Commit message (Collapse) | Author |
|
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>
|
|
- 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>
|
|
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>
|
|
- 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>
|
|
Fix various misspelling of "resource".
This commit changes the exported libucode ABI.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Subsequent requires of the same module returned the cached module instance
without increasing the refcount, leading to use-after-free on VM tear down
or garbage collection cycles.
Solve this issue by properly incrementing the refcount before returning
the cached module instance.
Fixes: #25
Fixes: 96f140b ("lib, vm: ensure that require() compiles modules only once")
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
When parsing the padding size specification of a `J` format, e.g. `%.4J`,
the internally called `atoi()` function might read beyond the end of the
initialized memory within the format buffer, leading to non-deterministic
results.
Avoid overreading the initialized memory by parsing the padding length
manually digit-by-digit.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Ensure that most functions follow the subject_verb naming schema
- Move type related function from value.c to types.c
- Rename value.c to vallist.c
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Ensure that all custom typedef and vector declaration type names end with
a "_t" suffix.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Instead of invoking exit(3) from uc_exit(), use a new EXCEPTION_EXIT
exception type to instruct the VM to shutdown cleanly.
This is required to not terminate the host program in case libucode
is embedded and loaded scripts invoke the exit() function.
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>
|
|
The naming is an artifact from before the introduction of the new type
system. In the current code, there is nothing special about prototypes,
they're simple object values.
Also introduce a new singular uc_add_function() convenience macro while
we're at it.
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 to increase the refcount of the module scope value when caching it
in the global module registry to avoid a double free on VM teardown.
Fixes: 96f140b ("lib, vm: ensure that require() compiles modules only once")
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Cache the result of a successful require operation in a global.modules
object and return the cached value for subsequent require calls on the
same module name.
This ensures that a given module is only compiled and executed once,
regardless of how many times it is used.
A reload of the module can be forced by deleting the corresponding
key in the global module table.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
This allows us to drop some token->instruction mapping case switches
in the VM.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The new functions allow encoding and decoding base64 values respectively.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Do not walk up the entire call stack but specifically use the context of the
callframe calling the C function.
Fixes: 3e893e6 ("lib: pass-through "this" context to library function callbacks")
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Ensure that callbacks invoked by filter(), map(), sort() and replace()
inherit the "this" context that invoked the respective C function.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The sourcepath() function allows querying the filesystem path of the source
file currently being executed by ucode.
The optional depth argument can be used to walk up the include stack to
determine the path of the file that included the current file, the path of
the parent file of the parent file and so on.
By specifying a truish value as second argument, only the directory portion
of the source file path is returned. This is useful to e.g. discover
ressources relative to the current source file directory.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The numeric return value was incorrectly stored in an unsigned size_t
variable which got later wrapped in an ucode signed 64bit integer value.
This worked by accident on 64bit systems since (int64_t)(size_t)(-1) == -1,
but it failed on 32bit ones where (int64_t)(size_t)(-1) yields 4294967295
due to the different sizes of the size_t and int64_t types.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Turn the Infinity and NaN keywords into global properties.
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>
|
|
Turn `delete` into a proper operator mimicking ECMAScript semantics.
Also ensure to transparently turn deprecated `delete(obj, propname)`
function calls into `delete obj.propname` expressions during compilation.
When strict mode is active, legacy delete() calls throw a syntax error
instead.
Finally drop the `delete()` function from the stdlib as it is shadowed
by the delete operator syntax now.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Provide a new ucode function regexp() which allows constructing regular
expression instances from separate source and flag strings.
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>
|
|
The internally used qsort(3) expects [-n, 0, n] return values from the
comparator function instead of a true/false value to denote lower than
or equal results.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Honour precision specifiers when parsing `J` format strings to enable or
disable JSON pretty printing.
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 split by string produces an initial empty string in the
result array when the string to split starts with the split substring
- Ensure that split by string produces a trailing empty string in the
result array when the string to split ends with the split substring
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Shuffle typedefs to avoid need for non-compliant forward declarations
- Fix non-compliant empty struct initializers
- Remove use of braced expressions
- Remove use of anonymous unions
- Avoid `void *` pointer arithmetic
- Fix several warnings reported by gcc -pedantic mode and clang 11 compilation
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>
|
|
Instead of relying on json_object values internally, use custom types to
represent the different ucode value types which brings a number of
advantages compared to the previous approach:
- Due to the use of tagged pointers, small integer, string and bool
values can be stored directly in the pointer addresses, vastly
reducing required heap memory
- Ability to create circular data structures such as
`let o; o = { test: o };`
- Ability to register custom `tostring()` function through prototypes
- Initial mark/sweep GC implementation to tear down circular object
graphs on VM deinit
The change also paves the way for possible future extensions such as
constant variables and meta methods for custom ressource types.
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>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Make sure to increase the refcount of items being moved since the
subsequent put operation will decrease it, prematurely freeing
moved items which will lead to use-after-free errors later on.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The ref count of the unshifted value returned by uc_unshift() must be
increased in order to prevent a subsequent double free within the VM
when the value eventually goes out of scope.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|