commit bc7ee6d4faa5754fe29b26f1c69033e7f78d00e6
parent 091d1f53bd22e6f0c8dfef8262e4313c08f04632
Author: Atila Butkovits <abutkovits@mozilla.com>
Date: Fri, 17 Oct 2025 16:18:43 +0300
Revert "Bug 1992107: Handle near overrecursion in RegExpDepthCheck. r=iain" for causing failures at RegExpCompiler.
This reverts commit 7c3cc4a7aa4ee76df736855165b44cca0d1a20c9.
Diffstat:
3 files changed, 26 insertions(+), 46 deletions(-)
diff --git a/js/public/friend/StackLimits.h b/js/public/friend/StackLimits.h
@@ -163,8 +163,6 @@ class MOZ_RAII AutoCheckRecursionLimit {
FrontendContext* fc) const;
[[nodiscard]] MOZ_ALWAYS_INLINE bool checkWithExtra(JSContext* cx,
size_t extra) const;
- [[nodiscard]] MOZ_ALWAYS_INLINE bool checkWithExtraDontReport(
- JSContext* cx, size_t extra) const;
[[nodiscard]] MOZ_ALWAYS_INLINE bool checkWithStackPointerDontReport(
JSContext* cx, void* sp) const;
[[nodiscard]] MOZ_ALWAYS_INLINE bool checkWithStackPointerDontReport(
@@ -287,22 +285,17 @@ MOZ_ALWAYS_INLINE bool AutoCheckRecursionLimit::checkWithStackPointerDontReport(
MOZ_ALWAYS_INLINE bool AutoCheckRecursionLimit::checkWithExtra(
JSContext* cx, size_t extra) const {
- if (MOZ_UNLIKELY(!checkWithExtraDontReport(cx, extra))) {
- ReportOverRecursed(cx);
- return false;
- }
- return true;
-}
-
-MOZ_ALWAYS_INLINE bool AutoCheckRecursionLimit::checkWithExtraDontReport(
- JSContext* cx, size_t extra) const {
char* sp = reinterpret_cast<char*>(__builtin_frame_address(0));
#if JS_STACK_GROWTH_DIRECTION > 0
sp += extra;
#else
sp -= extra;
#endif
- return checkWithStackPointerDontReport(cx, sp);
+ if (MOZ_UNLIKELY(!checkWithStackPointerDontReport(cx, sp))) {
+ ReportOverRecursed(cx);
+ return false;
+ }
+ return true;
}
MOZ_ALWAYS_INLINE bool AutoCheckRecursionLimit::checkSystem(
diff --git a/js/src/irregexp/RegExpAPI.cpp b/js/src/irregexp/RegExpAPI.cpp
@@ -417,10 +417,12 @@ class RegExpDepthCheck final : public v8::internal::RegExpVisitor {
}
// Leaf nodes with no children
-#define LEAF_DEPTH(Kind) \
- void* Visit##Kind(v8::internal::RegExp##Kind* node, void*) override { \
- AutoCheckRecursionLimit recursion(cx_); \
- return (void*)recursion.checkWithExtraDontReport(cx_, FRAME_PADDING); \
+#define LEAF_DEPTH(Kind) \
+ void* Visit##Kind(v8::internal::RegExp##Kind* node, void*) override { \
+ uint8_t padding[FRAME_PADDING]; \
+ dummy_ = padding; /* Prevent padding from being optimized away.*/ \
+ AutoCheckRecursionLimit recursion(cx_); \
+ return (void*)recursion.checkDontReport(cx_); \
}
LEAF_DEPTH(Assertion)
@@ -435,8 +437,10 @@ class RegExpDepthCheck final : public v8::internal::RegExpVisitor {
// Wrapper nodes with one child
#define WRAPPER_DEPTH(Kind) \
void* Visit##Kind(v8::internal::RegExp##Kind* node, void*) override { \
+ uint8_t padding[FRAME_PADDING]; \
+ dummy_ = padding; /* Prevent padding from being optimized away.*/ \
AutoCheckRecursionLimit recursion(cx_); \
- if (!recursion.checkWithExtraDontReport(cx_, FRAME_PADDING)) { \
+ if (!recursion.checkDontReport(cx_)) { \
return nullptr; \
} \
return node->body()->Accept(this, nullptr); \
@@ -450,8 +454,10 @@ class RegExpDepthCheck final : public v8::internal::RegExpVisitor {
void* VisitAlternative(v8::internal::RegExpAlternative* node,
void*) override {
+ uint8_t padding[FRAME_PADDING];
+ dummy_ = padding; /* Prevent padding from being optimized away.*/
AutoCheckRecursionLimit recursion(cx_);
- if (!recursion.checkWithExtraDontReport(cx_, FRAME_PADDING)) {
+ if (!recursion.checkDontReport(cx_)) {
return nullptr;
}
for (auto* child : *node->nodes()) {
@@ -463,8 +469,10 @@ class RegExpDepthCheck final : public v8::internal::RegExpVisitor {
}
void* VisitDisjunction(v8::internal::RegExpDisjunction* node,
void*) override {
+ uint8_t padding[FRAME_PADDING];
+ dummy_ = padding; /* Prevent padding from being optimized away.*/
AutoCheckRecursionLimit recursion(cx_);
- if (!recursion.checkWithExtraDontReport(cx_, FRAME_PADDING)) {
+ if (!recursion.checkDontReport(cx_)) {
return nullptr;
}
for (auto* child : *node->alternatives()) {
@@ -476,8 +484,10 @@ class RegExpDepthCheck final : public v8::internal::RegExpVisitor {
}
void* VisitClassSetExpression(v8::internal::RegExpClassSetExpression* node,
void*) override {
+ uint8_t padding[FRAME_PADDING];
+ dummy_ = padding; /* Prevent padding from being optimized away.*/
AutoCheckRecursionLimit recursion(cx_);
- if (!recursion.checkWithExtraDontReport(cx_, FRAME_PADDING)) {
+ if (!recursion.checkDontReport(cx_)) {
return nullptr;
}
for (auto* child : *node->operands()) {
@@ -490,6 +500,7 @@ class RegExpDepthCheck final : public v8::internal::RegExpVisitor {
private:
JSContext* cx_;
+ void* dummy_ = nullptr;
// This size is picked to be comfortably larger than any
// RegExp*::ToNode stack frame.
@@ -783,7 +794,8 @@ bool CompilePattern(JSContext* cx, MutableHandleRegExpShared re,
// Avoid stack overflow while recursively walking the AST.
RegExpDepthCheck depthCheck(cx);
if (!depthCheck.check(data.tree)) {
- ReportOverRecursed(cx);
+ JS_ReportErrorASCII(cx, "regexp too big");
+ cx->reportResourceExhaustion();
return false;
}
diff --git a/js/src/jit-test/tests/regexp/over-recursion-with-leaf-nodes.js b/js/src/jit-test/tests/regexp/over-recursion-with-leaf-nodes.js
@@ -1,25 +0,0 @@
-function hasChildNodes() {
- // Recurse so we get close to the stack limit.
- try {
- hasChildNodes();
- } catch {
- // Ignore over-recursion error.
- }
-
- // RegExp with child nodes.
- return RegExp(".|.").test("");
-}
-hasChildNodes();
-
-function hasLeafNode() {
- // Recurse so we get close to the stack limit.
- try {
- hasLeafNode();
- } catch {
- // Ignore over-recursion error.
- }
-
- // RegExp consisting of a single leaf node.
- return RegExp(".").test("");
-}
-hasLeafNode();