diff --git a/api/include/opentelemetry/context/runtime_context.h b/api/include/opentelemetry/context/runtime_context.h index 606cd79690..94be32bf18 100644 --- a/api/include/opentelemetry/context/runtime_context.h +++ b/api/include/opentelemetry/context/runtime_context.h @@ -241,6 +241,26 @@ class ThreadLocalContextStorage : public RuntimeContextStorage { friend class ThreadLocalContextStorage; + /** + * Limit the max stack depth. + * The stack will still work beyond this limit, + * counting push() and pop() properly, + * but will not record contexts. + * + * In practice, this should not affect instrumented applications, + * the limit is set to 1 million nested scopes. + * + * The whole reason for this limit to exist is to prevent + * compiler warnings like: + * error: argument 1 value ‘18446744073709551615’ + * exceeds maximum object size 9223372036854775807 + * [-Werror=alloc-size-larger-than=] + * on this line of code: + * Context *temp = new Context[new_capacity]; + * when compiling with gcc and optimizations (-flto). + */ + static constexpr size_t max_capacity_ = 1000000; + Stack() noexcept : size_(0), capacity_(0), base_(nullptr) {} // Pops the top Context off the stack. @@ -250,6 +270,11 @@ class ThreadLocalContextStorage : public RuntimeContextStorage { return; } + if (size_ > max_capacity_) + { + size_ -= 1; + return; + } // Store empty Context before decrementing `size`, to ensure // the shared_ptr object (if stored in prev context object ) are released. // The stack is not resized, and the unused memory would be reutilised @@ -278,6 +303,10 @@ class ThreadLocalContextStorage : public RuntimeContextStorage { return Context(); } + if (size_ > max_capacity_) + { + return Context(); + } return base_[size_ - 1]; } @@ -286,6 +315,10 @@ class ThreadLocalContextStorage : public RuntimeContextStorage void Push(const Context &context) noexcept { size_++; + if (size_ > max_capacity_) + { + return; + } if (size_ > capacity_) { Resize(size_ * 2); @@ -299,8 +332,14 @@ class ThreadLocalContextStorage : public RuntimeContextStorage size_t old_size = size_ - 1; if (new_capacity == 0) { + // First increase new_capacity = 2; } + if (new_capacity > max_capacity_) + { + // Last increase + new_capacity = max_capacity_; + } Context *temp = new Context[new_capacity]; if (base_ != nullptr) {