←back to thread

V8 Garbage Collector

(wingolog.org)
84 points swah | 1 comments | | HN request time: 0s | source
Show context
ZeroConcerns ◴[] No.45925770[source]
Interesting article! One thing that made me literally LOL was the fact that several exploits were enabled via a Google "style recommendation" that caused on-heap length fields to be signed and thus subject to sign-extension attacks.

The conversation-leading-up-to-that played out a bit like this in my head:

Google Engineer #1: Hey, shouldn't that length field be unsigned? Not like a negative value ever makes sense there?

GE#2: Style guide says no

GE#1: Yeah, but that could easily be exploited, right?

GE#2: Maybe, but at least I won't get dinged on code review: my metrics are already really lagging this quarter

GE#1: Good point! In fact, I'll pre-prepare an emergency patch for that whole thing, as my team lead indicated I've been a bit slow on the turnaround lately...

replies(2): >>45925968 #>>45925990 #
dbdr ◴[] No.45925990[source]
Quote from their style guide:

> The fact that unsigned arithmetic doesn't model the behavior of a simple integer, but is instead defined by the standard to model modular arithmetic (wrapping around on overflow/underflow), means that a significant class of bugs cannot be diagnosed by the compiler.

Fair enough, but signed arithmetic doesn't model the behavior of a "simple integer" (supposedly the mathematical concept) either. Instead, overflow in signed arithmetic is undefined behavior. Does that actually lead to the compiler being able to diagnose bugs? What's the claimed benefit exactly?

replies(3): >>45926013 #>>45926616 #>>45926636 #
gf000 ◴[] No.45926013[source]
I believe some logic behind may be that you can't recognize an overflow has happened with unsigned, but with signed you can recognize over and underflows in certain cases by simply checking if it's a non-negative number.

At least I believe Java decided on signed integers for similar reasons. But if it's indeed UB in C++, it doesn't make sense.

replies(1): >>45926378 #
alpinisme ◴[] No.45926378[source]
It’s the opposite in cpp: unsigned integer overflow is undefined but signed overflow is defined as wrapping
replies(2): >>45926584 #>>45926673 #
1. sltkr ◴[] No.45926673[source]
No, it's the opposite. UNSIGNED overflow wraps around. SIGNED overflow is undefined behavior.

This leads to fun behavior. Consider these functions which differ only in the type of the loop variable:

    int foo() {
        for (int i = 1; i > 0; ++i) {}
        return 42;
    }
    
    int bar() {
        for (unsigned i = 1; i > 0; ++i) {}
        return 42;
    }
If you compile these with GCC with optimization enabled, the result is:

    foo():
    .L2:
        jmp     .L2

    bar():
        mov     eax, 42
        ret
That is, foo() gets compiled into an infinite loop, while the loop in bar() is eliminated instead. This is because the compiler may assume only in the first case that i will never overflow.