[wasm][fuzzer] Optimize CheckMaxSteps with platform-specific code [v8/v8 : main]

0 views
Skip to first unread message

Clemens Backes (Gerrit)

unread,
7:30 AM (14 hours ago) 7:30 AM
to Daniel Lehmann, v8-s...@luci-project-accounts.iam.gserviceaccount.com, v8-mip...@googlegroups.com, v8-ppc...@googlegroups.com, v8-re...@googlegroups.com, v8-risc...@chromium.org, was...@google.com
Attention needed from Daniel Lehmann

Clemens Backes added 1 comment

Patchset-level comments
File-level comment, Patchset 3 (Latest):
Clemens Backes . resolved

PTAL.
This is both a performance and code size improvement (to make fuzzers faster) but it also fixes an issue with negative wraparound and with register pairs for 64-bit values on 32-bit platforms.

Open in Gerrit

Related details

Attention is currently required from:
  • Daniel Lehmann
Submit Requirements:
  • requirement satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: v8/v8
Gerrit-Branch: main
Gerrit-Change-Id: I430077703ea411f30749676569d1edeafb9ad3d8
Gerrit-Change-Number: 7849481
Gerrit-PatchSet: 3
Gerrit-Owner: Clemens Backes <clem...@chromium.org>
Gerrit-Reviewer: Clemens Backes <clem...@chromium.org>
Gerrit-Reviewer: Daniel Lehmann <dleh...@chromium.org>
Gerrit-Attention: Daniel Lehmann <dleh...@chromium.org>
Gerrit-Comment-Date: Tue, 19 May 2026 11:30:13 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
satisfied_requirement
unsatisfied_requirement
open
diffy

SLSA Policy Verification Service (Gerrit)

unread,
7:30 AM (14 hours ago) 7:30 AM
to Clemens Backes, Daniel Lehmann, v8-s...@luci-project-accounts.iam.gserviceaccount.com, v8-mip...@googlegroups.com, v8-ppc...@googlegroups.com, v8-re...@googlegroups.com, v8-risc...@chromium.org, was...@google.com
Attention needed from Daniel Lehmann

SLSA Policy Verification Service voted SLSA-Policy-Verified+1

SLSA-Policy-Verified+1
Open in Gerrit

Related details

Attention is currently required from:
  • Daniel Lehmann
Submit Requirements:
  • requirement satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: v8/v8
Gerrit-Branch: main
Gerrit-Change-Id: I430077703ea411f30749676569d1edeafb9ad3d8
Gerrit-Change-Number: 7849481
Gerrit-PatchSet: 3
Gerrit-Owner: Clemens Backes <clem...@chromium.org>
Gerrit-Reviewer: Clemens Backes <clem...@chromium.org>
Gerrit-Reviewer: Daniel Lehmann <dleh...@chromium.org>
Gerrit-Reviewer: SLSA Policy Verification Service <devtools-gerritco...@google.com>
Gerrit-Comment-Date: Tue, 19 May 2026 11:30:16 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
satisfied_requirement
unsatisfied_requirement
open
diffy

Daniel Lehmann (Gerrit)

unread,
8:13 AM (13 hours ago) 8:13 AM
to Clemens Backes, SLSA Policy Verification Service, v8-s...@luci-project-accounts.iam.gserviceaccount.com, v8-mip...@googlegroups.com, v8-ppc...@googlegroups.com, v8-re...@googlegroups.com, v8-risc...@chromium.org, was...@google.com
Attention needed from Clemens Backes

Daniel Lehmann voted Code-Review+1

Code-Review+1
Open in Gerrit

Related details

Attention is currently required from:
  • Clemens Backes
Submit Requirements:
  • requirement satisfiedCode-Owners
  • requirement satisfiedCode-Review
  • requirement satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: v8/v8
Gerrit-Branch: main
Gerrit-Change-Id: I430077703ea411f30749676569d1edeafb9ad3d8
Gerrit-Change-Number: 7849481
Gerrit-PatchSet: 3
Gerrit-Owner: Clemens Backes <clem...@chromium.org>
Gerrit-Reviewer: Clemens Backes <clem...@chromium.org>
Gerrit-Reviewer: Daniel Lehmann <dleh...@chromium.org>
Gerrit-Reviewer: SLSA Policy Verification Service <devtools-gerritco...@google.com>
Gerrit-Attention: Clemens Backes <clem...@chromium.org>
Gerrit-Comment-Date: Tue, 19 May 2026 12:13:46 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
satisfied_requirement
open
diffy

Daniel Lehmann (Gerrit)

unread,
8:13 AM (13 hours ago) 8:13 AM
to Clemens Backes, SLSA Policy Verification Service, v8-s...@luci-project-accounts.iam.gserviceaccount.com, v8-mip...@googlegroups.com, v8-ppc...@googlegroups.com, v8-re...@googlegroups.com, v8-risc...@chromium.org, was...@google.com
Attention needed from Clemens Backes

Daniel Lehmann voted Code-Review+0

Code-Review+0
Open in Gerrit

Related details

Attention is currently required from:
  • Clemens Backes
Submit Requirements:
  • requirement satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: v8/v8
Gerrit-Branch: main
Gerrit-Change-Id: I430077703ea411f30749676569d1edeafb9ad3d8
Gerrit-Change-Number: 7849481
Gerrit-PatchSet: 3
Gerrit-Owner: Clemens Backes <clem...@chromium.org>
Gerrit-Reviewer: Clemens Backes <clem...@chromium.org>
Gerrit-Reviewer: Daniel Lehmann <dleh...@chromium.org>
Gerrit-Reviewer: SLSA Policy Verification Service <devtools-gerritco...@google.com>
Gerrit-Attention: Clemens Backes <clem...@chromium.org>
Gerrit-Comment-Date: Tue, 19 May 2026 12:13:56 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
satisfied_requirement
unsatisfied_requirement
open
diffy

Daniel Lehmann (Gerrit)

unread,
8:14 AM (13 hours ago) 8:14 AM
to Clemens Backes, SLSA Policy Verification Service, v8-s...@luci-project-accounts.iam.gserviceaccount.com, v8-mip...@googlegroups.com, v8-ppc...@googlegroups.com, v8-re...@googlegroups.com, v8-risc...@chromium.org, was...@google.com
Attention needed from Clemens Backes

Daniel Lehmann added 1 comment

Patchset-level comments
Daniel Lehmann . resolved

Oops, mis-click, sorry for the noise.

Open in Gerrit

Related details

Attention is currently required from:
  • Clemens Backes
Submit Requirements:
  • requirement satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: v8/v8
Gerrit-Branch: main
Gerrit-Change-Id: I430077703ea411f30749676569d1edeafb9ad3d8
Gerrit-Change-Number: 7849481
Gerrit-PatchSet: 3
Gerrit-Owner: Clemens Backes <clem...@chromium.org>
Gerrit-Reviewer: Clemens Backes <clem...@chromium.org>
Gerrit-Reviewer: Daniel Lehmann <dleh...@chromium.org>
Gerrit-Reviewer: SLSA Policy Verification Service <devtools-gerritco...@google.com>
Gerrit-Attention: Clemens Backes <clem...@chromium.org>
Gerrit-Comment-Date: Tue, 19 May 2026 12:14:11 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
satisfied_requirement
unsatisfied_requirement
open
diffy

Daniel Lehmann (Gerrit)

unread,
9:41 AM (12 hours ago) 9:41 AM
to Clemens Backes, SLSA Policy Verification Service, v8-s...@luci-project-accounts.iam.gserviceaccount.com, v8-mip...@googlegroups.com, v8-ppc...@googlegroups.com, v8-re...@googlegroups.com, v8-risc...@chromium.org, was...@google.com
Attention needed from Clemens Backes

Daniel Lehmann added 12 comments

Patchset-level comments
Daniel Lehmann . resolved

I mostly have understanding problems/questions, since I'm looking at our fuzzer max step mechanism for the first time.

Commit Message
Line 21, Patchset 3 (Latest):3. Correct handling of 64-bit step counts (register pairs) on 32-bit
platforms (ia32, arm).
Daniel Lehmann . unresolved

I am not fully sure I understand: the step counter is a `int32_t*` pointer, i.e., can we even have 64-bit step counts? Or could we get rid of them if that makes things simpler? (This might be a stupid question / lacking context, since I never looked at our fuzzer step exhaustion mechanism so far.)

Line 23, Patchset 3 (Latest):4. Robust prevention of underflow/wraparound exploits by saturating
Daniel Lehmann . unresolved

`exploits` made it sound like this has a security implication, but IIUC this would simply be a (at worst DoS) bug, where the fuzzer continues execution for longer than max steps (well, indefinitely until a timeout, i.e., the step mechanism would be useless/ignored in that case), right?

File src/wasm/baseline/arm64/liftoff-assembler-arm64-inl.h
Line 2041, Patchset 3 (Latest): // If it underflowed, {Subs} will set the Carry (borrow) flag to 0.
Daniel Lehmann . unresolved

I like the explanation of the implementation details, but could you also add a high-level brief mention of the goal, namely that we want to saturate the step counter to `-1`.

Line 2039, Patchset 3 (Latest): Subs(max_steps.W(), max_steps.W(), reg.gp().W());
Daniel Lehmann . unresolved

Gemini tells me again that this line is buggy if `reg` contains a 64-bit step count, and one should use `max_steps.X()` instead? I'm still not quite sure (see also my high-level question on the commit message) whether we can have 64-bit step counts, so maybe this is WAI?

File src/wasm/baseline/ia32/liftoff-assembler-ia32-inl.h
Line 2235, Patchset 3 (Latest): sbb(scratch, scratch);
Daniel Lehmann . unresolved

Same comment as below, I'd appreviate a very brief comment explaining/mentioning the saturation.

Line 2231, Patchset 3 (Latest): Register scratch = pinned.set(GetUnusedRegister(kGpReg, pinned)).gp();
Daniel Lehmann . unresolved

Since this needs 3 unused registers but those are really scarce on ia32, what happens or has it already happened in the past that we run out of registers?

Line 2218, Patchset 3 (Latest): if (auto* reg = std::get_if<LiftoffRegister>(&steps);
Daniel Lehmann . unresolved

nit: you could use an unconditional `std::get<LiftoffRegister>` here since the if above returns early otherwise, right?

File src/wasm/baseline/liftoff-compiler.cc
Line 1270, Patchset 3 (Latest): CheckMaxSteps(decoder, static_cast<int32_t>(16 + __ num_locals()));
Daniel Lehmann . unresolved

Just to double check: `steps_done` is using an `int32_t` instead of `uint32_t` from `num_locals` to avoid silent unsigned integer overflow, right? Although in practice, that would have never been an issue, since `num_locals` is way below 2^31 due to our implementation limits, right?

File src/wasm/baseline/x64/liftoff-assembler-x64-inl.h
Line 1895, Patchset 3 (Latest): sbbq(scratch, scratch);
Daniel Lehmann . unresolved

While clever, I didn't immediately understand the `sbbq` + `orl` saturating subtraction without some reviewing with Gemini. Can we add a comment here, explaining or at least mentioning this here (since readers are not going to dig up the commit message in the future to realize this saturation). Something something "If the previous subtraction underflowed (counter < steps), expand the carry flag to -1 and then mask with that, to cap the counter at -1."

Line 1894, Patchset 3 (Latest): subl(max_steps, std::get<LiftoffRegister>(steps).gp());
Daniel Lehmann . unresolved

Doesn't `subl` operate only on the 32-bit part of the register, i.e., would be wrong for 64-bit step counts?

File test/fuzzer/wasm/module/regress-513298282.wasm
Daniel Lehmann . unresolved

Just to double check: This module contains an infinite loop or something that triggers this "fuel"/exhaustion fuzzer limits on execution?

Open in Gerrit

Related details

Attention is currently required from:
  • Clemens Backes
Submit Requirements:
    • requirement satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: v8/v8
    Gerrit-Branch: main
    Gerrit-Change-Id: I430077703ea411f30749676569d1edeafb9ad3d8
    Gerrit-Change-Number: 7849481
    Gerrit-PatchSet: 3
    Gerrit-Owner: Clemens Backes <clem...@chromium.org>
    Gerrit-Reviewer: Clemens Backes <clem...@chromium.org>
    Gerrit-Reviewer: Daniel Lehmann <dleh...@chromium.org>
    Gerrit-Reviewer: SLSA Policy Verification Service <devtools-gerritco...@google.com>
    Gerrit-Attention: Clemens Backes <clem...@chromium.org>
    Gerrit-Comment-Date: Tue, 19 May 2026 13:41:39 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    SLSA Policy Verification Service (Gerrit)

    unread,
    12:19 PM (9 hours ago) 12:19 PM
    to Clemens Backes, Daniel Lehmann, v8-s...@luci-project-accounts.iam.gserviceaccount.com, v8-mip...@googlegroups.com, v8-ppc...@googlegroups.com, v8-re...@googlegroups.com, v8-risc...@chromium.org, was...@google.com
    Attention needed from Clemens Backes

    SLSA Policy Verification Service voted SLSA-Policy-Verified+1

    SLSA-Policy-Verified+1
    Open in Gerrit

    Related details

    Attention is currently required from:
    • Clemens Backes
    Submit Requirements:
    • requirement satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: v8/v8
    Gerrit-Branch: main
    Gerrit-Change-Id: I430077703ea411f30749676569d1edeafb9ad3d8
    Gerrit-Change-Number: 7849481
    Gerrit-PatchSet: 4
    Gerrit-Owner: Clemens Backes <clem...@chromium.org>
    Gerrit-Reviewer: Clemens Backes <clem...@chromium.org>
    Gerrit-Reviewer: Daniel Lehmann <dleh...@chromium.org>
    Gerrit-Reviewer: SLSA Policy Verification Service <devtools-gerritco...@google.com>
    Gerrit-Attention: Clemens Backes <clem...@chromium.org>
    Gerrit-Comment-Date: Tue, 19 May 2026 16:19:23 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: Yes
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Clemens Backes (Gerrit)

    unread,
    12:20 PM (9 hours ago) 12:20 PM
    to SLSA Policy Verification Service, Daniel Lehmann, v8-s...@luci-project-accounts.iam.gserviceaccount.com, v8-mip...@googlegroups.com, v8-ppc...@googlegroups.com, v8-re...@googlegroups.com, v8-risc...@chromium.org, was...@google.com
    Attention needed from Daniel Lehmann

    Clemens Backes added 13 comments

    Patchset-level comments
    Daniel Lehmann . resolved

    I mostly have understanding problems/questions, since I'm looking at our fuzzer max step mechanism for the first time.

    Clemens Backes

    Sorry, I should have pointed to https://crrev.com/c/7840281 somewhere for context. And I didn't choose Matthias as reviewer because he was out yesterday.

    File-level comment, Patchset 4 (Latest):
    Clemens Backes . resolved

    Sorry, it's a pretty large delta from PS3 to PS4 because we now need to pass the ValueKind to handle 64-bit values correctly on 64-bit platforms, but also handle register pairs on 32-bit platforms.

    It's a fresh upload, if anything gets red I'll take a look tomorrow.

    Commit Message
    Line 21, Patchset 3:3. Correct handling of 64-bit step counts (register pairs) on 32-bit
    platforms (ia32, arm).
    Daniel Lehmann . unresolved

    I am not fully sure I understand: the step counter is a `int32_t*` pointer, i.e., can we even have 64-bit step counts? Or could we get rid of them if that makes things simpler? (This might be a stupid question / lacking context, since I never looked at our fuzzer step exhaustion mechanism so far.)

    Clemens Backes

    We do pass a dynamic value for the number of steps to subtract. That value can e.g. come from the input to `memory.grow` and that can be an i64 value for memory64. That's not a great example as we can never grow by 2^32 pages, but it illustrates the problem.

    Line 23, Patchset 3:4. Robust prevention of underflow/wraparound exploits by saturating
    Daniel Lehmann . resolved

    `exploits` made it sound like this has a security implication, but IIUC this would simply be a (at worst DoS) bug, where the fuzzer continues execution for longer than max steps (well, indefinitely until a timeout, i.e., the step mechanism would be useless/ignored in that case), right?

    Clemens Backes

    Right.

    File src/wasm/baseline/arm64/liftoff-assembler-arm64-inl.h
    Line 2041, Patchset 3: // If it underflowed, {Subs} will set the Carry (borrow) flag to 0.
    Daniel Lehmann . resolved

    I like the explanation of the implementation details, but could you also add a high-level brief mention of the goal, namely that we want to saturate the step counter to `-1`.

    Clemens Backes

    The goal is not to saturate at -1, but to prevent negative wraparound into the positive range. I added a comment.

    Line 2039, Patchset 3: Subs(max_steps.W(), max_steps.W(), reg.gp().W());
    Daniel Lehmann . resolved

    Gemini tells me again that this line is buggy if `reg` contains a 64-bit step count, and one should use `max_steps.X()` instead? I'm still not quite sure (see also my high-level question on the commit message) whether we can have 64-bit step counts, so maybe this is WAI?

    Clemens Backes

    Hm, it has a point. We shouldn't just use `max_steps.X()`, but we should probably look at the upper half of the value as well, and stop immediately if any bit is set. Did that in the new patchset.

    File src/wasm/baseline/ia32/liftoff-assembler-ia32-inl.h
    Line 2235, Patchset 3: sbb(scratch, scratch);
    Daniel Lehmann . resolved

    Same comment as below, I'd appreviate a very brief comment explaining/mentioning the saturation.

    Clemens Backes

    Done

    Line 2231, Patchset 3: Register scratch = pinned.set(GetUnusedRegister(kGpReg, pinned)).gp();
    Daniel Lehmann . resolved

    Since this needs 3 unused registers but those are really scarce on ia32, what happens or has it already happened in the past that we run out of registers?

    Clemens Backes

    Hasn't happened yet. If it happens in fuzzing we will run into DCHECK failures and we will need to fix it.

    Line 2218, Patchset 3: if (auto* reg = std::get_if<LiftoffRegister>(&steps);
    Daniel Lehmann . resolved

    nit: you could use an unconditional `std::get<LiftoffRegister>` here since the if above returns early otherwise, right?

    Clemens Backes

    Right, done.

    File src/wasm/baseline/liftoff-compiler.cc
    Line 1270, Patchset 3: CheckMaxSteps(decoder, static_cast<int32_t>(16 + __ num_locals()));
    Daniel Lehmann . resolved

    Just to double check: `steps_done` is using an `int32_t` instead of `uint32_t` from `num_locals` to avoid silent unsigned integer overflow, right? Although in practice, that would have never been an issue, since `num_locals` is way below 2^31 due to our implementation limits, right?

    Clemens Backes

    Right, it shouldn't make a difference if we pass this as `uint32_t` or `int32_t`. There's a DCHECK below that ensures that it's always a relatively small integer anyway.

    File src/wasm/baseline/x64/liftoff-assembler-x64-inl.h
    Line 1895, Patchset 3: sbbq(scratch, scratch);
    Daniel Lehmann . resolved

    While clever, I didn't immediately understand the `sbbq` + `orl` saturating subtraction without some reviewing with Gemini. Can we add a comment here, explaining or at least mentioning this here (since readers are not going to dig up the commit message in the future to realize this saturation). Something something "If the previous subtraction underflowed (counter < steps), expand the carry flag to -1 and then mask with that, to cap the counter at -1."

    Clemens Backes

    Sure, totally makes sense. This is AI generated code of course, and AI often forgets to add some minimal comments. I'll try to remember to ask it more to add comments.

    Line 1894, Patchset 3: subl(max_steps, std::get<LiftoffRegister>(steps).gp());
    Daniel Lehmann . resolved

    Doesn't `subl` operate only on the 32-bit part of the register, i.e., would be wrong for 64-bit step counts?

    Clemens Backes

    Right, this is the same problem as on arm64. I fixed it in the new patchset.

    File test/fuzzer/wasm/module/regress-513298282.wasm
    File-level comment, Patchset 3:
    Daniel Lehmann . resolved

    Just to double check: This module contains an infinite loop or something that triggers this "fuel"/exhaustion fuzzer limits on execution?

    Clemens Backes

    No, this triggered the DCHECK from the bug by executing a memory.grow on a 64-bit memory if I remember correctly.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Daniel Lehmann
    Submit Requirements:
    • requirement satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: v8/v8
    Gerrit-Branch: main
    Gerrit-Change-Id: I430077703ea411f30749676569d1edeafb9ad3d8
    Gerrit-Change-Number: 7849481
    Gerrit-PatchSet: 4
    Gerrit-Owner: Clemens Backes <clem...@chromium.org>
    Gerrit-Reviewer: Clemens Backes <clem...@chromium.org>
    Gerrit-Reviewer: Daniel Lehmann <dleh...@chromium.org>
    Gerrit-Reviewer: SLSA Policy Verification Service <devtools-gerritco...@google.com>
    Gerrit-Attention: Daniel Lehmann <dleh...@chromium.org>
    Gerrit-Comment-Date: Tue, 19 May 2026 16:20:41 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Daniel Lehmann <dleh...@chromium.org>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy
    Reply all
    Reply to author
    Forward
    0 new messages