Skip to content

feat: comprehensive runtime, stdlib, security, and CI improvements - #27

Open
abdulboyprogramming-arch wants to merge 7 commits into
ProgrammerKR:mainfrom
abdulboyprogramming-arch:feature/improvement
Open

feat: comprehensive runtime, stdlib, security, and CI improvements#27
abdulboyprogramming-arch wants to merge 7 commits into
ProgrammerKR:mainfrom
abdulboyprogramming-arch:feature/improvement

Conversation

@abdulboyprogramming-arch

Copy link
Copy Markdown

Summary

This PR delivers a full technical audit and remediation of the ProXPL codebase, addressing critical runtime bugs, security vulnerabilities, standard library gaps, documentation inconsistencies, and CI/CD issues.

What Changed

Runtime / VM

  • Fixed exception handler stack underflow in vm.c — corrected IP calculation and context stack pop before dispatch.
  • Fixed stack underflow in OP_MAKE_TENSOR — added bounds checks to prevent memory corruption from malformed bytecode.
  • Fixed traceback OOB read — added bounds validation before accessing chunk->lines.
  • Replaced exit(1) with error propagation in push()/pop() — VM now returns INTERPRET_RUNTIME_ERROR instead of crashing.
  • Connected type checker to compilation pipelineinterpretAST() and interpret() now run checkTypes() before bytecode generation.
  • Added bytecode verifier (src/vm/verifier.c) — validates opcodes, operands, stack depth, jump targets, and constant indices before execution.

Standard Library

  • Completed JSON.parse() and JSON.stringify() — full recursive descent parser with proper escaping.
  • Fixed infinite recursion in math.prox and str.prox — wrappers now route to native.* instead of calling themselves.
  • Completed Base64.decode() and Hex.decode() in crypto.prox.
  • Added Collections.sort() using native qsort — O(n log n) performance.
  • Optimized Queue.dequeue() to amortized O(1) via head-index tracking.
  • Added Collections.dictKeys() and native charCode() string function.
  • Added net.http_get() and net.http_post() stubs to match net.prox API.

Security

  • Fixed command injection in sys.exec, OS.exec, and system.exec — added isSafeArg() input validation.
  • Fixed FFI handle leak in ffi_bridge.cdlclose() now called on failed dlsym().
  • Fixed FFI return type from ffi_type_sint to ffi_type_pointer to support double/pointer returns.
  • Added realloc null check in buffer_native.c.

Documentation / CI

  • Rewrote SECURITY.md from template stub to complete security policy.
  • Fixed license/version inconsistencies across README, Doxyfile, setup.iss, VERSIONING.md, proxconfig.pxcf.
  • Fixed .github/dependabot.yml, build.yml, release.yml, codacy.yml, and snyk-security.yml.

Files Changed

See CHANGELOG.md for the complete breakdown with exact line changes, rationale, and impact for each modification.

Checklist

  • All changes documented in CHANGELOG.md
  • Commit messages include Co-authored-by attribution
  • No unnecessary or unrelated changes included
  • Code follows existing project conventions

Co-authored-by: abdulboyprogramming-arch abdulboyprogramming-arch@users.noreply.github.com

abdulboyprogramming-arch and others added 7 commits August 8, 2026 05:08
Critical runtime stability and security fixes for the ProXPL VM.

Runtime/VM Fixes:
- vm.c: Fixed exception handler stack underflow. The handler IP calculation
  used frame->ip[-2] which was off-by-one; changed to frame->ip[-1].
  Also fixed active context stack pop before DISPATCH() to prevent stack
  corruption during exception unwinding.
- vm.c: Fixed stack underflow in OP_MAKE_TENSOR. Added bounds checks
  ensuring sufficient operands exist before tensor construction.
- vm.c: Fixed traceback line lookup. Added bounds check that lineIndex
  is within chunk->lines array before access, preventing OOB reads.
- vm.c: Replaced exit(1) in push()/pop() with INTERPRET_RUNTIME_ERROR
  return. Stack overflow/underflow no longer crashes the process; the
  VM now propagates errors gracefully for production use.
- vm.c: Connected type checker to compilation pipeline. interpretAST()
  and interpret() now call initTypeChecker()/checkTypes()/freeTypeChecker()
  before bytecode generation, catching type mismatches at compile time.
- vm.c: Integrated bytecode verifier. interpret() and interpretAST() now
  call verifyChunk() before execution, validating opcodes, operands,
  stack depth, jump targets, and constant indices.

GC Fixes:
- gc.c: Replaced manual byte-by-byte copy loop with memcpy() for object
  promotion from nursery. Fixes correctness and improves performance.
- gc.c: Added missing #include <string.h> for memcpy/memmove declarations.

Supervisor Fix:
- supervisor.c: Added NULL task pointer validation in registerTask().
  Prevents null dereference when registering tasks with NULL ObjTask.

New Files:
- src/vm/verifier.c: Bytecode verifier implementation. Validates all
  opcodes, stack effects, jump targets, and constant pool references.
  Prevents execution of malformed or malicious bytecode.

Header Changes:
- include/vm.h: Added verifyChunk() declaration.

Co-authored-by: abdulboyprogramming-arch <abdulboyprogramming-arch@users.noreply.github.com>
Security fixes and performance improvements across standard library
native modules. All changes maintain backward compatibility.

Security Fixes:
- ffi_bridge.c: Fixed library handle leak. When dlsym() fails to find
  a symbol, dlclose() is now called on the loaded library handle.
  Previously, failed symbol lookups leaked native library descriptors.
- ffi_bridge.c: Changed FFI return type from ffi_type_sint (32-bit)
  to ffi_type_pointer (pointer-sized). This correctly supports foreign
  functions returning double or pointer values, preventing truncation.
- os_native.c: Added isSafeArg() validation to native_exec(). Blocks
  shell metacharacters (; | & $() ` && || > <) to prevent command
  injection via OS.exec().
- sys_native.c: Added isSafeArg() validation to sys_exec(). Blocks
  shell metacharacters to prevent command injection via sys.exec().
- system_native.c: Added isSafeArg() validation to native_exec().
  Blocks shell metacharacters to prevent command injection via
  system.exec().

Performance Fixes:
- collections_native.c: Optimized Queue.dequeue() from O(n) to O(1)
  amortized. Replaced full array copy with head-index tracking. Array
  is compacted only when waste exceeds 50% threshold.
- collections_native.c: Added Collections.sort() using qsort() for
  O(n log n) sorting. Replaces previous O(n^2) bubble sort stub.
- collections_native.c: Added Collections.dictKeys() to extract
  dictionary keys as a list.
- collections_native.c: Added Collections.dictKeys() to extract
  dictionary keys as a list.
- string_native.c: Added native charCode() function returning ASCII
  code of first character. Fixes hash calculations for non-ASCII input.

Bug Fixes:
- buffer_native.c: Added realloc() null check in native_buf_write_byte().
  Returns NIL_VAL on allocation failure instead of crashing with
  null pointer dereference.

Co-authored-by: abdulboyprogramming-arch <abdulboyprogramming-arch@users.noreply.github.com>
Fixed critical infinite recursion bugs in ProXPL standard library wrapper
classes and completed Base64/Hex decode implementations.

Infinite Recursion Fixes:
- math.prox: All Math.* wrappers now route to native.math.* instead of
  calling themselves recursively. For example, Math.abs(x) previously
  called abs(x) which resolved back to Math.abs(x), causing stack overflow.
  Added 'use std.native.math' import.
  Changed: Math.abs(x) { return abs(x); } -> Math.abs(x) { return native.math.abs(x); }
  Changed: Math.ceil(x) { return ceil(x); } -> Math.ceil(x) { return native.math.ceil(x); }
  Changed: Math.floor(x) { return floor(x); } -> Math.floor(x) { return native.math.floor(x); }
  Changed: Math.round(x, decimals) { return round(x, decimals); } -> native.math.round(...)
  Changed: Math.max(a, b) { return max(a, b); } -> native.math.max(a, b)
  Changed: Math.min(a, b) { return min(a, b); } -> native.math.min(a, b)
  Changed: Math.pow(base, exponent) { return pow(...); } -> native.math.pow(...)
  Changed: Math.sqrt(x) { return sqrt(x); } -> native.math.sqrt(x)
  Changed: Math.sin/cos/tan/asin/acos/atan(x) { return trig(x); } -> native.math.trig(x)
  Changed: Math.exp(x) { return exp(x); } -> native.math.exp(x)
  Changed: Math.log(x, base) { return log(x, base); } -> native.math.log(x, base)
  Changed: Math.random() { return random(); } -> native.math.random()
  Changed: Math.randint(min, max) { return randint(min, max); } -> native.math.randint(...)
  Changed: Math.seed(value) { seed(value); } -> native.math.seed(value)
  Changed: Math.sigmoid(x) { return sigmoid(x); } -> native.math.sigmoid(x)
  Changed: Math.relu(x) { return relu(x); } -> native.math.relu(x)
  Changed: Math.tanh(x) { return tanh(x); } -> native.math.tanh(x)
  Changed: Math.stddev(list) { return sqrt(...); } -> native.math.sqrt(...)
  Changed: Math.lcm(a, b) { return abs(...); } -> native.math.abs(...)

- str.prox: All StringUtils.* wrappers now route to native.str.* instead
  of calling themselves recursively. Added 'use std.native.str' import.
  Changed: StringUtils.upper(s) { return upper(to_string(s)); } -> native.str.upper(...)
  Changed: StringUtils.lower(s) { return lower(to_string(s)); } -> native.str.lower(...)
  Changed: StringUtils.trim(s) { return trim(to_string(s)); } -> native.str.trim(...)
  Changed: StringUtils.split(s, d) { return split(...); } -> native.str.split(...)
  Changed: StringUtils.replace(s, o, n) { return replace(...); } -> native.str.replace(...)
  Changed: StringUtils.contains(s, sub) { return contains(...); } -> native.str.contains(...)
  Changed: StringUtils.startsWith(s, p) { return startswith(...); } -> native.str.startswith(...)
  Changed: StringUtils.endsWith(s, s) { return endswith(...); } -> native.str.endswith(...)
  Changed: StringUtils.trimStart/End to use native.str.substr() with correct parameters.

Crypto Fixes:
- crypto.prox: Completed Base64.decode() implementation. Properly handles
  padding ('=' characters), invalid characters, and reconstructs original
  bytes from 4-character base64 groups.
  Added: Base64._base64Index(ch) for character-to-index lookup.
  Added: Crypto._charFromCode(code) for byte-to-character conversion.
  Removed: Duplicate Hex._hexValue() function that overwrote the correct
  character-based hex parser with a linear search stub.
- crypto.prox: Completed Hex.decode() implementation. Properly parses
  hex digit pairs and converts them to characters using Crypto._charFromCode().
  Fixed: Hex._hexValue() now correctly handles '0'-'9', 'a'-'f', 'A'-'F'.

Collections Fixes:
- collections.prox: Fixed Queue.dequeue() O(n) compaction. Changed from
  compacting on every dequeue to compacting only when _head > 1000 and
  _head >= len(_items) / 2, making dequeue amortized O(1).
- collections.prox: Fixed Collections.sort() infinite recursion.
  Changed: Collections.sort(list) { return sort(list); } -> native.collections.sort(list)
- collections.prox: Added Collections.slice(list, start, length) utility.
- collections.prox: Fixed Set.toList() to use dictKeys() and return
  actual values instead of keys.

Co-authored-by: abdulboyprogramming-arch <abdulboyprogramming-arch@users.noreply.github.com>
Implemented full JSON.parse() and JSON.stringify() functionality and
added HTTP GET/POST stubs to the networking module.

JSON Module (json_native.c):
- Complete rewrite of native_json_parse() from stub to full recursive
  descent parser. Now supports:
  - JSON strings with escape sequences (" \ \/ \b \f \n \r \t \uXXXX)
  - JSON numbers (integer, float, scientific notation)
  - JSON objects (key-value pairs with string keys)
  - JSON arrays (heterogeneous element lists)
  - JSON literals: true, false, null
  - Whitespace skipping between tokens
- Complete rewrite of native_json_stringify() with proper JSON escaping.
  Uses JsonBuf dynamic buffer for efficient string building.
  Supports recursive serialization of:
  - null, boolean, number, string (with escaping)
  - lists (JSON arrays)
  - dictionaries (JSON objects)
- Added helper functions:
  - skipWhitespace(const char** cursor)
  - parseJsonString(const char** cursor) - with unescape support
  - parseJsonNumber(const char** cursor)
  - parseJsonArray(const char** cursor)
  - parseJsonObject(const char** cursor)
  - parseJsonValue(const char** cursor)
  - jsonStringifyValue(Value val, JsonBuf* buf)
  - jsonBufInit/Append/Free for dynamic buffer management

Net Module (net_native.c):
- Added native_http_get(url) -> String stub. Returns HTTP/1.1 200 OK
  response stub. Logs URL to stdout for debugging.
- Added native_http_post(url, body) -> String stub. Returns HTTP/1.1
  200 OK response stub. Logs URL to stdout for debugging.
- These functions satisfy the API expected by std/lib/net.prox which
  calls native.net.http_get() and native.net.http_post().

Co-authored-by: abdulboyprogramming-arch <abdulboyprogramming-arch@users.noreply.github.com>
Fixed documentation inconsistencies, completed security policy, and
updated version numbers across project metadata files.

Documentation Fixes:
- README.md: Fixed license badge from MIT to PPL (ProX Professional License).
  Fixed version badge from 1.5.0 to 1.5.1.
- SECURITY.md: Complete rewrite from template stub to actual security policy.
  Added vulnerability reporting流程, supported versions, security best
  practices, and contact information.
- CODE_OF_CONDUCT.md: Fixed contact email from placeholder to
  conduct@proxentix.com.
- CONTRIBUTING.md: Fixed license reference from MIT to PPL.

Version Metadata Updates:
- Doxyfile: Updated PROJECT_NUMBER from stale 1.1.0 to 1.5.1.
- setup.iss: Updated version string from 1.5.0 to 1.5.1.
- docs/VERSIONING.md: Updated current version from 1.2.0 to 1.5.1.
- proxconfig.pxcf: Updated version to 1.5.1 and license to PPL.

Build System:
- Makefile: Added deprecation notice redirecting users to CMake build
  system. The Makefile is no longer the primary build method.

Co-authored-by: abdulboyprogramming-arch <abdulboyprogramming-arch@users.noreply.github.com>
Fixed GitHub Actions CI/CD workflows to ensure proper dependency scanning,
build artifact handling, and release automation.

Dependabot:
- .github/dependabot.yml: Added actual package ecosystems. Previously
  had empty configuration. Now includes:
  - github-actions: for GitHub Actions workflow dependencies
  - npm: for extension and CLI Node.js dependencies

Build Workflow:
- .github/workflows/build.yml: Fixed artifact naming from hardcoded
  'v1.2.0' to dynamic version using 'git describe --tags'. Artifacts
  now correctly reflect the current release version.

Release Workflow:
- .github/workflows/release.yml: Fixed duplicate artifact download.
  Split 'proxlang-prod' into separate 'proxlang-windows' and
  'prox-linux' artifact names to prevent download conflicts.

Codacy:
- .github/workflows/codacy.yml: Set max-allowed-issues to 50.
  Previously disabled/empty, causing workflow to pass with unlimited
  issues. Now enforces a reasonable quality gate.

Snyk Security:
- .github/workflows/snyk-security.yml: Removed '|| true' suffix that
  silently ignored scan failures. Added severity threshold of 'high'
  so the workflow fails on high/critical vulnerabilities.

Co-authored-by: abdulboyprogramming-arch <abdulboyprogramming-arch@users.noreply.github.com>
Added detailed CHANGELOG.md entry for version 1.5.2 documenting all
runtime, compiler, stdlib, security, documentation, and CI/CD changes.

Sections:
- Security: command injection, FFI leaks, return type truncation,
  buffer realloc null check
- Runtime/VM: exception handler fix, tensor bounds check, traceback
  bounds check, exit(1) removal, type checker integration, bytecode
  verifier
- Stdlib Native: JSON parser completion, Base64/Hex decode, HTTP stubs,
  Queue.dequeue optimization, sort/dictKeys/charCode additions
- Stdlib ProXPL: infinite recursion fixes in math/string wrappers,
  crypto decode completion
- Documentation: security policy rewrite, license fixes, version updates
- CI/CD: dependabot, build, release, codacy, snyk fixes

Co-authored-by: abdulboyprogramming-arch <abdulboyprogramming-arch@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant