Ask coding questions

← Back to all posts
[Closed] Coalescing if statements leads to change in control flow?
xxpertHacker (934)

On line 228 of base64.hpp, I had this:

if ( '=' == ascii[i] ) {
	if ( '=' != ascii[1 + i] ) {
		return false;
	}
}

I looked at this, and thought that I could just use an && operator, like so:

if ( '=' == ascii[i] && '=' != ascii[1 + i] ) {
	return false;
}

Then my tests crashed and the program aborted...

How are these not the same?

if x {
    if y {
        return false;
    }
}
// vs
if x && y {
    return false;
}
Comments
hotnewtop
xxpertHacker (934)

@DynamicSquid Umm... so, I never figured this out, and I think it happened without optimization applied too, do you think you could take a look?

It's mostly pointer arithmetic, comparisons, and memory writing/reading; very simple C-like code.

DynamicSquid (4891)

@xxpertHacker I don't have much time right now, but I'll take a look at it again in a couple hours.

xxpertHacker (934)

@DynamicSquid Re-ping, whenever you have plenty of extra time, could you review this and check the Repl yourself?

Hopefully the code is not too hard to intuitively understand.

DynamicSquid (4891)

@xxpertHacker What compiler are you using? I'm assuming Clang? I think it has something to do with how the compiler implements the && operator.

xxpertHacker (934)

@DynamicSquid Well... I can try G++...

Update: I was using clang++-10, but I can't install-pkg any of the gcc versions onto Repl :/

DynamicSquid (4891)

@xxpertHacker is it an array out of bounds error? because you know "smart &&" operator? like it stops at the first condition that is false? but maybe the compiler doesn't doesn't implement it? or you changed the compiler settings

sorry Im on my phone rn, I cant really give you an example. when i get home I can show you what I mean with an example

xxpertHacker (934)

@DynamicSquid Umm... it's a plain char8_t const * const, where char8_t is an eight-bit, unsigned byte.

i is a std::size_t const.

These are primitive types without any operator overloading, or any of that fun stuff ;)

There is no bounds checking on the [] operator, since it's the raw C [] operator.

Didn't change the compiler settings, I set -O0 for debugging.

The semantics of && are, afaik:

v = x() && y()
// equivalent to:
v = if x() {
  y()
} else {
  false
}

Which is exactly why I thought that I could use an && here, to make the code more terse.

The current code uses an if branch, so it's already lazily computed.

Both indexes are in-bounds, so I could just as easily use &.

xxpertHacker (934)

@DynamicSquid Nevermind, it just hit me, it was an if else, changing the semantics and control flow.

DynamicSquid (4891)

@xxpertHacker Wait, that was the problem, it was part of an if else? That was very anticlimactic lol

xxpertHacker (934)

@DynamicSquid Yup, literally the lamest possible bug that I could accidentally create.

Coder100 (18057)

are you SURE that's what is causing the tests to fail?

They are the same thing

xxpertHacker (934)

@Coder100 I swear, I JUST tried it to make sure; try it yourself: https://repl.it/@xxpertHacker/base64#base64.hpp lines 228-231.

You'll get std::bad_optional_access thrown at that point, that just means that the function believes that the base64 was invalid, since you'd be breaking the base64 integrity checking function.

xxpertHacker (934)

@Coder100 Did you ever try it yourself?

Baconman321 (1096)

This happens to me in JavaScript too.

I think it would mainly be something logical..

Hmmm... (thinking). I'll edit it when I find an answer (or don't find an answer).

Baconman321 (1096)

@xxpertHacker Yeah I don't think I found an answer :(