| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
Make plugin API cleanup functions noexcept (#13590) Exceptions have never been a supported error channel across the plugin API, but that contract was never written down, so one escaping into a plugin destructor terminated the process with no attribution. Annotate the 28 cleanup and teardown functions noexcept, each a function-try-block that aborts naming the function, and contain formatting failures inside ts::do_abort and _call_fatal, whose message building allocates. Mangled names are unchanged; the guide is updated. | 11 天前 | |
Test AtomicSharedPtr concurrency (#13566) Add Catch2 coverage for AtomicSharedPtr load/store/exchange operations and concurrent readers during writer swaps. Also clarify the fallback implementation comment so it no longer relies on stale library-version shorthand. | 21 天前 | |
Annotate BRAVO locks for thread-safety analysis (#13330) * Annotate BRAVO locks for thread-safety analysis Enabling -Wthread-safety tree-wide surfaced findings in Bravo.h on macOS, where libc++ marks the underlying std::shared_mutex as a capability: the wrapper acquires and releases it across method boundaries and on fast/slow-path branches the analyzer cannot follow. Fedora CI uses libstdc++, which does not annotate std types, so it never saw these. Make ts::bravo::shared_mutex_impl a real capability so the contract is checked on every Clang, not papered over on one std lib; its lock-driving bodies are the trusted implementation and stay exempted, matching the ts::shared_mutex pattern. Make the reader guard a rigid scoped capability -- acquire in constructor, release in destructor, no copy/move/defer/release -- which the analysis tracks with no exemption; the movable std::shared_lock-style forms it replaced could not be tracked, and no caller used them. Restructure the unit test's try-lock asserts so the acquire gates a branch. * Reset BRAVO Token on entry to harden slow-path unlock lock_shared/try_lock_shared assigned the Token only on the fast path, so a reused non-zero Token surviving into a slow-path acquisition would make unlock_shared release a reader slot instead of the underlying mutex. Clear it on entry to enforce the documented 0-init contract. | 2 个月前 | |
Avoid signed tolower for name bytes Client-controlled SNI and Host bytes are lowercased while ATS matches TLS SNI configuration, selects certificate entries, and prints normalized effective URLs. Passing negative signed char values to std::tolower is undefined behavior and can become a crash in hardened or debug C library builds. This routes byte normalization through unsigned char before calling std::tolower and keeps the normalized output byte-compatible. | 1 个月前 | |
Restore DbgCtl::_rm_reference() for ABI compatibility (#12797) PR #12777 introduced a leaky singleton pattern for DbgCtl to fix use-after-free crashes during shutdown. However, removing the _rm_reference() method broke ABI compatibility with existing plugins that were compiled against the old header, where the destructor called this method. This commit restores _rm_reference() as a no-op stub, allowing old plugins to load successfully while maintaining the leaky singleton behavior. | 7 个月前 | |
Fix DenseThreadId static destruction order fiasco (#12789) The _id_stack vector was being destroyed before thread-local _Id objects, causing use-after-free when _Id::~_Id() tried to write to the freed vector. This patch addresses this by using std::array instead of std::vector. Since std::array<std::size_t, N> has a trivial destructor, the memory remains valid to the threads trying to use it regardless of destruction order. This bug was latent and only exposed when linking order changed (e.g., when adding new source files that changed static initialization order). Here's the valgrind output diagnosing the issue being fixed here: ==29149== Invalid write of size 8 ==29149== at 0x565832: DenseThreadId::_Id::~_Id() ==29149== by 0x6126DD8: ??? (in /usr/lib64/libstdc++.so.6.0.19) ==29149== by 0x6B40059: __cxa_finalize (in /usr/lib64/libc-2.17.so) ==29149== ... ==29149== Address 0xd4be1c0 is 0 bytes inside a block of size 2,048 free'd ==29149== at 0x4C2B6DF: operator delete(void*, unsigned long) ==29149== by 0x6B40059: __cxa_finalize (in /usr/lib64/libc-2.17.so) ==29149== ... ==29149== Block was alloc'd at ==29149== at 0x4C2A593: operator new(unsigned long) ==29149== by 0x566820: std::vector<...>::_M_default_append(unsigned long) ==29149== by 0x56515C: __tls_init | 8 个月前 | |
Fix an infinite loop in Histogram (#11752) The loop in Histogram::operator() is infinite if R = 7, S = 2, and sample = 512. When this happens, the histogram will not find a matching bit and will loop forever with mask at 0. This change lowers OVERFLOW_BOUND so that every sample is guaranteed to have a 1-bit within the range of histogram buckets. | 2 年前 | |
clang-format v18 + modified configs (#11285) | 2 年前 | |
Allow a metric to be unlisted (#13616) * Allow a metric to be unlisted A metric name, once created, was published for the life of the process. Any metric whose name or publication policy depends on a runtime changeable setting could therefore never retract a name it had already published, so such a setting only ever took effect for names created after the change. Unlisting takes a slot out of the store's listing. It keeps its slot, its name and its atomic, so lookup by name still resolves and creating the name again relists it with its value intact. Iteration skips it, which is what removes it from traffic_ctl, the JSONRPC record lookup and stats_over_http without any of them changing. * Make iterator comparison terminate across snapshots Each iterator captures its own bound, and exhaustion was judged against that. A subrange whose stop iterator was made later held a larger bound, so the walk could pass its own bound and go on comparing unequal to a stop that was still live, with operator++ unable to make progress. Two find() calls with a metric created between them was enough. Exhaustion between two positional iterators is now judged against the earlier of the two bounds, so such a subrange ends at the earlier snapshot. The sentinel keeps its own answer, since its bound means nothing. * Anchor the unlisted-tail test in its own metric It asserted the store had at least one listed metric left, which depends on what other sections put there. A listed metric of its own says the same thing without that coupling. * Say which iterator comparisons are meaningful Exhaustion is a property of an iterator's own snapshot bound, so two taken at different times can compare equal to each other while disagreeing about end. That is not a total equivalence relation, which makes these unfit for a generic algorithm; only same snapshot comparisons, and comparison against end, are meaningful. * Frame the snapshot as the sequence, not as a caveat The previous note disclaimed the equivalence relation while the type still declared input_iterator_tag, which advertises what it then denied. A snapshot is the sequence: iterators from different ones are no more comparable than iterators into different containers, so mixing them is unspecified rather than broken, and within one snapshot equality is the relation an input iterator requires. * Replace metric iteration with for_each A public iterator lets a caller name a position, and a position stops meaning anything once iteration skips unlisted slots. An iterator held at a slot that is later unlisted becomes a range bound the walk steps straight over and never reaches, and find() could hand back the next listed metric rather than the one asked for. Supporting either would mean defining iterator invalidation for listing changes, to keep a surface with no callers: every consumer walks the whole store, and find() had none at all. for_each is the whole store or nothing. With no cursor to outlive the walk, the equality rules, the snapshot bound comparison and find() go away along with the defects they carried. lookup() remains the way to reach a single metric by name. | 2 小时前 | |
clang-format v18 + modified configs (#11285) | 2 年前 | |
Regex: compile the copy for the JIT engine (#13685) pcre2_code_copy() duplicates a compiled pattern but not the machine code the JIT produced for it, so every copied Regex matched on the interpreter: same answers, far slower, and under different resource limits, which is how an original and a copy disagree about whether a subject is acceptable at all. maxmind_acl copies every rule. Compile the copy for the JIT as compile() does, and check the null pcre2_code_copy() returns on OOM, which previously went straight to pcre2_jit_compile(); a failed copy now leaves the object empty. | 4 小时前 | |
clang-format v18 + modified configs (#11285) | 2 年前 | |
clang-format v18 + modified configs (#11285) | 2 年前 | |
Restore a shortcut in hot loop in _mime_hdr_field_list_search_by_string (#13119) * Restore a shortcut in hot loop in _mime_hdr_field_list_search_by_string * Add ts::iequals(const std::string_view &, const std::string_view &) * Address issue from Copilot | 4 个月前 | |
Fix coverity complaint #1550451 (#11663) Co-authored-by: Chris McFarlen <cmcfarlen@apple.com> | 2 年前 | |
Introduce Clang Thread Safety Analysis, and apply it to two subsystems (#13310) Add TS_* annotation macros (tsutil/ts_thread_safety.h) wrapping Clang's -Wthread-safety attributes, so a lock's contract -- which mutex guards which data, which lock a function requires its caller to hold -- can be expressed in the type system and proved at build time. They expand to nothing off Clang: no runtime cost, and a no-op for GCC. Add annotated lock types for the analysis to track: ts::mutex with ts::lock_guard, and ts::shared_mutex (already ATS's own rwlock) marked as a capability with ts::write_guard / ts::read_guard. Annotated code takes its locks through these because the std:: RAII wrappers are too flexible -- deferred locking, move, adopt/release -- for the analysis to track, and ATS does not need that flexibility. The guard names mirror std::lock_guard's rigid acquire-in-constructor / release-in-destructor RAII rather than implying std::unique_lock's flexibility. Add the ENABLE_THREAD_SAFETY_ANALYSIS option (Clang-only, on by default as a warning) and THREAD_SAFETY_ANALYSIS_AS_ERROR, which the CI and branch presets enable so violations are errors that gate merges while local and dev builds stay warnings. Install the new headers with the rest of tsutil, and add a unit test compiled with the analysis enabled as a worked example. Skip FreeBSD: its libc annotates the pthread primitives themselves, so -Wthread-safety there flags ATS's existing hand-rolled mutex wrappers (tscore/ink_mutex.h and others) tree-wide; bringing FreeBSD into the gate needs those legacy wrappers made analysis-clean first. Apply the analysis to two subsystems: Metrics::Storage: valid(), lookup(IdType) and name() read _cur_blob/_cur_off/_blobs with no lock held, while create()/createSpan()/ current() access the same fields under the mutex (rename() likewise read them before locking). A single Storage is shared by all threads, so a metric registered at runtime -- a plugin TSStatCreate or a config reload -- advances those fields while live traffic reads them: a data race. Take the mutex on every access and mark the fields guarded by it; the reads that were missing a lock take it exclusively, matching the existing locked paths. SSLOriginSessionCache: the origin session map and queue are reachable from every thread; mark them guarded by the cache mutex so the compiler enforces the locking that was previously only convention. Replace the hand-rolled lock witness on remove_oldest_session (a std::unique_lock parameter checked with owns_lock()) with a compile-time TS_REQUIRES precondition. | 2 个月前 | |
Make plugin API cleanup functions noexcept (#13590) Exceptions have never been a supported error channel across the plugin API, but that contract was never written down, so one escaping into a plugin destructor terminated the process with no attribution. Annotate the 28 cleanup and teardown functions noexcept, each a function-try-block that aborts naming the function, and contain formatting failures inside ts::do_abort and _call_fatal, whose message building allocates. Mangled names are unchanged; the guide is updated. | 11 天前 | |
Add abuse_shield plugin (#13586) Operators need a unified way to detect abusive clients, exempt trusted networks, and enforce policy without unbounded per-client memory growth. Request floods, connection floods, HTTP/2 errors, and TLS fingerprints otherwise require separate controls. This patch adds abuse_shield with per-IP token-bucket limits, trusted and tiered IP policies, and configurable logging, temporary blocking, and connection closing. Bounded tracking tables limit memory use, while live configuration reloads, state clearing, and metrics support ongoing operation. The plugin also matches ClientHello fingerprints before ServerHello through a shared JAx registry supporting JA3, JA4, and downstream methods. New session-error accessors enable HTTP/2 connection-error accounting even before a transaction exists. Documentation and unit and integration tests cover configuration, rate limits, fingerprint matching, and enforcement. Co-authored-by: Codex Astra Medium | 23 小时前 | |
clang-format v18 + modified configs (#11285) | 2 年前 | |
Introduce tsutil from tsapicore and tscpputil (#10928) * move tsapicore to tsutil * Move tscpp/util to tsutil * cmake format * cleanup remaining tscore deps from tsutil * what on earth | 2 年前 | |
Introduce tsutil from tsapicore and tscpputil (#10928) * move tsapicore to tsutil * Move tscpp/util to tsutil * cmake format * cleanup remaining tscore deps from tsutil * what on earth | 2 年前 | |
Fix last left unused parameters in the project (#11471) * Fix last left unused parameters in the project Remove the warning supporession for unused parameters * Fix forgotten unused parameter in bw_log function * Fix unused parameters in the cripts module * Fix unused parameters reported only by Clang compiler in template code * Fix unused parameters in the lua plugin * Return back temporary the -Wno-unused-parameter warning suppression * Restore back `alloc` parameter name in swoc/Vectray functionality | 2 年前 | |
Introduce tsutil from tsapicore and tscpputil (#10928) * move tsapicore to tsutil * Move tscpp/util to tsutil * cmake format * cleanup remaining tscore deps from tsutil * what on earth | 2 年前 | |
Introduce tsutil from tsapicore and tscpputil (#10928) * move tsapicore to tsutil * Move tscpp/util to tsutil * cmake format * cleanup remaining tscore deps from tsutil * what on earth | 2 年前 | |
Introduce Clang Thread Safety Analysis, and apply it to two subsystems (#13310) Add TS_* annotation macros (tsutil/ts_thread_safety.h) wrapping Clang's -Wthread-safety attributes, so a lock's contract -- which mutex guards which data, which lock a function requires its caller to hold -- can be expressed in the type system and proved at build time. They expand to nothing off Clang: no runtime cost, and a no-op for GCC. Add annotated lock types for the analysis to track: ts::mutex with ts::lock_guard, and ts::shared_mutex (already ATS's own rwlock) marked as a capability with ts::write_guard / ts::read_guard. Annotated code takes its locks through these because the std:: RAII wrappers are too flexible -- deferred locking, move, adopt/release -- for the analysis to track, and ATS does not need that flexibility. The guard names mirror std::lock_guard's rigid acquire-in-constructor / release-in-destructor RAII rather than implying std::unique_lock's flexibility. Add the ENABLE_THREAD_SAFETY_ANALYSIS option (Clang-only, on by default as a warning) and THREAD_SAFETY_ANALYSIS_AS_ERROR, which the CI and branch presets enable so violations are errors that gate merges while local and dev builds stay warnings. Install the new headers with the rest of tsutil, and add a unit test compiled with the analysis enabled as a worked example. Skip FreeBSD: its libc annotates the pthread primitives themselves, so -Wthread-safety there flags ATS's existing hand-rolled mutex wrappers (tscore/ink_mutex.h and others) tree-wide; bringing FreeBSD into the gate needs those legacy wrappers made analysis-clean first. Apply the analysis to two subsystems: Metrics::Storage: valid(), lookup(IdType) and name() read _cur_blob/_cur_off/_blobs with no lock held, while create()/createSpan()/ current() access the same fields under the mutex (rename() likewise read them before locking). A single Storage is shared by all threads, so a metric registered at runtime -- a plugin TSStatCreate or a config reload -- advances those fields while live traffic reads them: a data race. Take the mutex on every access and mark the fields guarded by it; the reads that were missing a lock take it exclusively, matching the existing locked paths. SSLOriginSessionCache: the origin session map and queue are reachable from every thread; mark them guarded by the cache mutex so the compiler enforces the locking that was previously only convention. Replace the hand-rolled lock witness on remove_oldest_session (a std::unique_lock parameter checked with owns_lock()) with a compile-time TS_REQUIRES precondition. | 2 个月前 | |
Introduce tsutil from tsapicore and tscpputil (#10928) * move tsapicore to tsutil * Move tscpp/util to tsutil * cmake format * cleanup remaining tscore deps from tsutil * what on earth | 2 年前 | |
Coverity Fixes (#12821) * Fix Coverity CID 1644341: Suppress false positive for bravo lock The ts::bravo::shared_lock properly holds the mutex but Coverity doesn't recognize this custom lock class. Add suppression comment. * Fix Coverity CID 1644338: Handle exceptions in Stripe destructor Wrap potentially throwing diagnostic code (Dbg, ink_assert) in try-catch to ensure destructor never throws. Memory cleanup continues regardless. * Fix Coverity CID 1644337: Suppress false positive for copy assignment test The test intentionally uses copy assignment (not move) to verify copy assignment operator behavior. Add suppression comment. * Fix Coverity CID 1644336: Initialize entrylist before scandir Initialize entrylist to nullptr before passing to scandir to satisfy static analysis, even though scandir allocates the memory. * Fix Coverity CID 1644335: Make StaticString thread-safe Add proper mutex protection to StaticString: - Add mutex locks to _createString() and lookup() - Add for_each() method for thread-safe iteration - Remove begin()/end() which exposed non-thread-safe iterators - Update RecCore.cc to use for_each() * Fix Coverity CID 1644332/1644314: Suppress false positive in State destructor Add suppression comment. The destroy() method only frees memory and does ref counting - it cannot throw. * Fix Coverity CID 1644330: Suppress false positive for visitor pattern The visitor intentionally moves from the variant alternative to consume it. The caller should not use the moved-from value after the visitor returns. * Fix Coverity CID 1644329: Remove noexcept from UnitParser::operator() The function calls Lexicon::operator[] which uses std::visit internally and can throw std::domain_error for unknown unit names. Remove noexcept to allow the exception to propagate. * Fix Coverity CID 1644324: Handle exceptions in HttpSM destructor Wrap m_remap->release() in try-catch since it can allocate (new_Deleter). Add suppression comments for other calls that cannot throw. * Fix Coverity CID 1644319: Use memcpy instead of strcpy Replace strcpy with memcpy using explicit length from string_view. This satisfies static analysis even though the assert validates the size. Also explicitly null-terminate the destination. * Fix Coverity CID 1644318: Add null check before strcmp Add REQUIRE(result->hostname \!= nullptr) before strcmp calls to ensure the pointer is valid, preventing potential null dereference. * Fix Coverity CID 1644316: PASS_BY_VALUE in IOBuffer.cc Make the Lexicon static to avoid capturing 360 bytes by value in the lambda. The lambda now captures nothing and references the static lexicon directly. * Fix Coverity CID 1644312: Suppress false positive RESOURCE_LEAK Add suppression comment for false positive. The heap is freed via hdr.destroy() -> HdrHeapSDKHandle::destroy() -> m_heap->destroy(). * Fix Coverity CID 1644310: COPY_INSTEAD_OF_MOVE in regex_remap.cc Use std::move when assigning opt_val to _strategy since opt_val is not used again after this assignment in the strategy branch. * Fix Coverity CID 1644323: CHECKED_RETURN in ts_util.cc Check the return value of TSCacheUrlSet and return an error Errata if the call fails. * Fix Coverity CID 1644326: OVERRUN in test_HpackIndexingTable.cc Add Coverity suppression comment for false positive. The len parameter is validated positive by REQUIRE(len > 0) before the memcmp call, but Coverity doesn't recognize that REQUIRE throws on failure. * Fix Coverity CID 1644325: WRAPPER_ESCAPE in test_RemapPlugin.cc Add Coverity suppression for false positive. The plugin pointer temporarily escapes to pluginThreadContext in doneInstance() but is properly reset via resetPluginContext() before the method returns. * Fix Coverity CID 1644320: UNCAUGHT_EXCEPT in traffic_crashlog.cc Add Coverity suppression for false positive. The std::optional access via ats_as_c_str() is properly guarded by checking the optional has a value before calling the function. * Fix Coverity CID 1644327: UNCAUGHT_EXCEPT in test_AIO.cc Add Coverity suppression. Functions called from main() may throw exceptions, but this is a test program where uncaught exceptions will terminate with a stack trace, which is acceptable behavior. * Fix inverted condition that could throw std::bad_optional_access The RECD_COUNTER case in plugin_expand() had an inverted condition: 'if (count_val)' instead of 'if (!count_val)'. This caused the code to call .value() on an empty optional when the counter record was not found, throwing std::bad_optional_access. This matches the pattern used in the RECD_FLOAT and RECD_INT cases. | 7 个月前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 11 天前 | ||
| 21 天前 | ||
| 2 个月前 | ||
| 1 个月前 | ||
| 7 个月前 | ||
| 8 个月前 | ||
| 2 年前 | ||
| 2 年前 | ||
| 2 小时前 | ||
| 2 年前 | ||
| 4 小时前 | ||
| 2 年前 | ||
| 2 年前 | ||
| 4 个月前 | ||
| 2 年前 | ||
| 2 个月前 | ||
| 11 天前 | ||
| 23 小时前 | ||
| 2 年前 | ||
| 2 年前 | ||
| 2 年前 | ||
| 2 年前 | ||
| 2 年前 | ||
| 2 年前 | ||
| 2 个月前 | ||
| 2 年前 | ||
| 7 个月前 |