Skip to content

Fix critical memory safety bugs, improve thread stability, and introduce JSON ownership API - #39

Open
lozatto wants to merge 12 commits into
Next21Team:mainfrom
lozatto:fix/crashes-memory-corruption
Open

Fix critical memory safety bugs, improve thread stability, and introduce JSON ownership API#39
lozatto wants to merge 12 commits into
Next21Team:mainfrom
lozatto:fix/crashes-memory-corruption

Conversation

@lozatto

@lozatto lozatto commented Aug 24, 2026

Copy link
Copy Markdown

Fix critical memory corruption crashes, resolve OpenSSL thread-safety issues, separate HTTP/FTP session caches, and introduce a safer JSON ownership model for Pawn developers.

What was updated

  • The ezhttp_option_set_body_from_json() native now requires an explicit EzJSONOwnership tag instead of a raw EzJSON handle.
  • Developers must explicitly use ezjson_move() or ezjson_copy() to pass JSON objects to HTTP options. This forces compiler validation (preventing silent handle misuse) and enables the C++ module to safely consume and invalidate the handle upon a move.
  • Added strict length bounds validation for Pawn arrays in ReadCallbackData and ezhttp_option_set_user_data to prevent Out-Of-Bounds (OOB) memory reads and massive heap allocations.

What was improved

  • Thread Safety: Fixed OpenSSL crashes on Linux by properly registering locking callbacks, preventing SIGSEGV during concurrent HTTPS requests.
  • Signals: Enforced CURLOPT_NOSIGNAL across all cURL operations to prevent unpredictable SIGALRM crashes.
  • Server Pause Starvation: Prevented unbounded memory growth when the AMXX engine is paused (sv_paused 1) by implementing queue backpressure. Worker threads now block gracefully if the completion queue hits its limit, instead of endlessly hogging RAM.
  • Dangling Callbacks: Eliminated FTP Use-After-Free vulnerabilities by explicitly nullifying CURLOPT_READFUNCTION and CURLOPT_WRITEFUNCTION (and their DATA counterparts) immediately after FTP transfers, preventing cURL from executing destroyed stack lambdas.
  • Session Cache Leakage: Separated HTTP and FTP session caches by injecting the protocol scheme (https://, ftp://) into the cache key.
  • Memory Leaks: Fixed a persistent memory leak in UrlUtils::GetHostByUrl where libcurl host strings were not being freed.
  • Shutdown Lifecycle: Refactored the module destruction and worker thread join sequence (CancelAllRequests()) to prevent deadlocks and ensure proper cleanup during plugin unload or map changes.
  • Build System: Fixed CMake build failures on Linux by explicitly finding and linking OpenSSL::Crypto.

Test improvements

  • Updated ez_http_test.sma to comply with the new ezjson_move() ownership API.
  • Removed redundant ezjson_free() calls in the test plugin, as the JSON handle is now inherently consumed and freed by the C++ backend when moved.

Documentation

  • easy_http.inc and easy_http_json.inc were updated with the new EzJSONOwnership tag and helper stocks.
  • The documentation now makes it explicitly clear that using ezjson_move() transfers the ownership to the HTTP request and invalidates the handle on the Pawn side.

#20

#32

@lozatto

lozatto commented Aug 24, 2026

Copy link
Copy Markdown
Author

I was experiencing several server crashes that I traced back to missing validations. I also took the opportunity to address two related issues in the same update.

I have been testing these changes for about a week now, and since implementing them, we have not experienced any of the crashes mentioned previously.

Another issue I fixed was related to cURL. When the server crashed for any reason, EasyHTTP was sometimes unable to recover because there were multiple pending requests during the EasyHTTP module's shutdown/recovery process. After fixing this behavior, I have not experienced the issue again.

@Polarhigh
Polarhigh self-requested a review August 26, 2026 13:54
@lozatto

lozatto commented Aug 27, 2026

Copy link
Copy Markdown
Author

@Polarhigh Fixed a critical SIGBUS crash that occurred during ReHLDS/ReGameDLL updates. The issue was caused by calling the engine API CVarGetFloat to check the trace log setting on every single server frame (StartFrame). The module now reads the locally cached cvar_t value directly, which not only prevents memory corruption crashes on engine mismatches but also significantly improves overall server performance.

@lozatto

lozatto commented Aug 28, 2026

Copy link
Copy Markdown
Author

@Polarhigh If you'd like, instead of using EzJSONOwnership, I can change it for you. However, it has been working well as it is.

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