Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/cli/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ void print_usage() {
fmt::print(" --env <name> Apply environment overrides from govern.json\n");
fmt::print("\nSecurity Options:\n");
fmt::print(" --sandbox-level <level> Security: restricted|standard|elevated|unrestricted\n");
fmt::print(" (default: standard - safe for enterprise)\n");
fmt::print(" (default: unrestricted)\n");
fmt::print(" --timeout <seconds> Execution timeout per block (default: 30)\n");
fmt::print(" --memory-limit <MB> Memory limit per block (default: 512)\n");
fmt::print(" --allow-network Enable network access (default: disabled)\n");
Expand Down
10 changes: 9 additions & 1 deletion src/interpreter/naab_val.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <mutex>
#include <stdexcept>
#include <vector>
#include <climits>
#include <cmath>

namespace naab {
namespace interpreter {
Expand Down Expand Up @@ -504,7 +506,13 @@ bool NaabVal::toBool() const {

int NaabVal::toInt() const {
if (isInt()) return asInt();
if (isDouble()) return static_cast<int>(asDouble());
if (isDouble()) {
double d = asDouble();
if (std::isnan(d)) return 0;
if (d >= static_cast<double>(INT_MAX)) return INT_MAX;
if (d <= static_cast<double>(INT_MIN)) return INT_MIN;
return static_cast<int>(d);
}
if (isBool()) return asBool() ? 1 : 0;
if (isHeap()) return asHeap()->shared_value->toInt();
return 0;
Expand Down
1 change: 1 addition & 0 deletions src/runtime/block_search_index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ class BlockSearchIndex::Impl {
}
if (ec) {
fmt::print("[ERROR] Failed to open blocks directory: {}\n", blocks_path);
sqlite3_exec(db_, "ROLLBACK;", nullptr, nullptr, nullptr);
return 0;
}

Expand Down
3 changes: 1 addition & 2 deletions src/runtime/bounded_read.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ std::optional<std::string> readFileBounded(const std::string& path,
// This eliminates the lstat-then-ifstream TOCTOU race.
int fd = ::open(path.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
if (fd < 0) return std::nullopt;
struct FdGuard { int f; ~FdGuard() { if (f >= 0) ::close(f); } } guard{fd};

struct stat st;
if (::fstat(fd, &st) != 0 || !S_ISREG(st.st_mode)) {
::close(fd);
return std::nullopt;
}

Expand All @@ -41,7 +41,6 @@ std::optional<std::string> readFileBounded(const std::string& path,
}
content.append(buf, chunk);
}
::close(fd);
if (n < 0) return std::nullopt;
return content;
#else
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/governance_reports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ void GovernanceEngine::logAuditEvent(const std::string& event_type,
entry["event"] = event_type;
entry["rule"] = rule_name;
entry["message"] = message;
if (!file.empty()) entry["file"] = file;
if (!file.empty()) entry["file"] = error::ErrorSanitizer::sanitizeFilePaths(file);
if (line > 0) entry["line"] = line;

// Include config rationale in audit entries when available
Expand Down
12 changes: 9 additions & 3 deletions src/runtime/resource_limits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ static std::atomic<uint64_t> g_win_timer_generation{0};
#else
// V-RT-007: cancel flag for the POSIX timer thread (set by clearTimeout()).
std::atomic<bool> ResourceLimiter::posix_timer_cancel_{false};
// Generation counter for cancellable POSIX timer threads (matches Windows pattern).
static std::atomic<uint64_t> g_posix_timer_generation{0};
#endif

void ResourceLimiter::installSignalHandlers() {
Expand Down Expand Up @@ -95,14 +97,15 @@ void ResourceLimiter::setExecutionTimeout(unsigned int seconds) {
// concurrent call to setExecutionTimeout() has its own independent timer.
pthread_t tid = pthread_self();
posix_timer_cancel_.store(false, std::memory_order_relaxed);
std::thread([seconds, tid]() {
uint64_t my_gen = ++g_posix_timer_generation;
std::thread([seconds, tid, my_gen]() {
using clock = std::chrono::steady_clock;
auto deadline = clock::now() + std::chrono::seconds(seconds);
while (clock::now() < deadline) {
if (ResourceLimiter::posix_timer_cancel_.load(std::memory_order_relaxed)) return;
if (g_posix_timer_generation.load(std::memory_order_relaxed) != my_gen) return;
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
if (!ResourceLimiter::posix_timer_cancel_.load(std::memory_order_relaxed)) {
if (g_posix_timer_generation.load(std::memory_order_relaxed) == my_gen) {
// Set global_shutdown_ first so isTimeoutTriggered() returns true
// even if the signal is not delivered immediately (e.g. tight loops
// on Android/Termux where SIGALRM may stay pending).
Expand Down Expand Up @@ -139,6 +142,9 @@ void ResourceLimiter::setExecutionTimeout(unsigned int seconds) {
void ResourceLimiter::clearTimeout() {
#ifndef _WIN32
// V-RT-007: cancel the posix timer thread and any residual system alarm.
// Bump generation counter to invalidate any in-flight timer thread
// (matches Windows pattern — stale timer sees mismatched generation and exits).
++g_posix_timer_generation;
posix_timer_cancel_.store(true, std::memory_order_relaxed);
alarm(0);
#else
Expand Down
5 changes: 4 additions & 1 deletion src/stdlib/agent_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <fmt/core.h>
#include <stdexcept>
#include <cstdlib>
#include <random>
#include <unordered_set>
#include <mutex>
#include <future>
Expand Down Expand Up @@ -1495,7 +1496,9 @@ static NaabVal agentSend(std::vector<NaabVal>& args) {
if (config->retry.jitter && delay > 0) {
int jitter_range = delay / 4;
if (jitter_range > 0) {
delay += (std::rand() % (2 * jitter_range + 1)) - jitter_range;
static thread_local std::mt19937 rng(std::random_device{}());
std::uniform_int_distribution<int> dist(-jitter_range, jitter_range);
delay += dist(rng);
}
}
if (delay > 0) {
Expand Down
9 changes: 8 additions & 1 deletion src/stdlib/json_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <fmt/core.h>
#include <stdexcept>
#include <sstream>
#include <climits>
#include <cstdint>

using json = nlohmann::json;

Expand Down Expand Up @@ -108,7 +110,12 @@ interpreter::NaabVal jsonToValue(const json& j) {
} else if (j.is_boolean()) {
return interpreter::NaabVal::makeBool(j.get<bool>());
} else if (j.is_number_integer()) {
return interpreter::NaabVal::makeInt(j.get<int>());
auto val = j.get<int64_t>();
if (val >= INT_MIN && val <= INT_MAX) {
return interpreter::NaabVal::makeInt(static_cast<int>(val));
} else {
return interpreter::NaabVal::makeDouble(static_cast<double>(val));
}
} else if (j.is_number_float()) {
return interpreter::NaabVal::makeDouble(j.get<double>());
} else if (j.is_string()) {
Expand Down
Loading