[Not really OT] Crowdstrike Analysis: It was a NULL pointer from the memory unsafe C++ language.

Richard (Rikki) Andrew Cattermole richard at cattermole.co.nz
Sat Jul 27 19:00:46 UTC 2024


On 28/07/2024 6:33 AM, Walter Bright wrote:
> On 7/27/2024 2:30 AM, Richard (Rikki) Andrew Cattermole wrote:
>> There are two solutions for a native language that isn't just ignoring 
>> it like we do today. Check it at CT and warn/error if you do not 
>> handle null, or inject read barriers like we do for bounds checks to 
>> cause the runtime exception.
> 
> How is `assert(p != null)` better?

Two reasons.

1. You made the decision. You had to consider what would happen in this 
situation. The question was asked, what happens should this be null? If 
you want to assert that's fine. What is not fine is making an assumption 
and never state it, never have it proven to be true.

2. It throws an exception (in D), which can be caught safely. It is only 
when exception chaining occurs that the state may not have been cleaned 
up correctly.

An even better solution to using an assert, is to use an if statement 
instead.

```d
if (int* ptr = var.field) {
	// success
} else {
	// fail, you can gracefully degrade/log here
}
```

With the help of ``?.`` operator, we can also make this very nice to use 
for loads and stores, AND be temporally safe!

```d
if (S1* ptr1 = var.field1) {
	if (S2* ptr2 = ptr1.field2) {
		// success
		goto AfterFailure;
	}
}

// failure

AfterFailure:
```

From:

```d
if (int* ptr = var?.field1?.field2) {
	// success
} else {
	// failure
}
```

>> Note: this is solved in C/C++ world. They have such analysis in their 
>> compilers: analyzer-null-dereference
>>
>> https://gcc.gnu.org/onlinedocs/gcc-10.1.0/gcc/Static-Analyzer-Options.html
> 
> -Wanalyzer-possible-null-argument
> 
> That's not solving it.

Yes and no.

It cannot solve it completely in C or C++ because there is no language 
integration.

For temporal safety, you have to make sure you do a load into a 
variable, and only then do the test.

Which means this:

```d
void func(int** ptr) {
	assert(*ptr !is null);

	int i = **ptr; // ERROR: `**ptr` is in an unknown type state, it could 
be null
}
```

> Many simple cases can indeed be found by DFA. But not all. There's also 
> a lot of DFA trying to eliminate array bounds errors, but such errors 
> remain the #1 security problem with C and C++.
> 
> D does insert checks for array bounds overflow, because the hardware is 
> of no help.

I agree about bounds checks. However as read barriers, these are things 
that we do control, and throw an exception that we can catch.

For this reason, bounds checks do not need CT analysis. They do not have 
to bring down an application if caught.

On the other hand, null dereference requires signal handling to catch. 
If you don't own thread and process you cannot use that to throw an 
exception. For this reason it's not comparable and requires CT analysis 
to prevent bringing down the process.

On the other hand, if you were to propose read barriers that throw 
exceptions for null dereference, I would agree to the statement that 
they are comparable.

>> It only takes one major outage where a business loses money before 
>> they consider dumping a D companies solution. No client wants to hear: 
>> "We did this in a known unsafe language for this particular error, 
>> when a more main stream language has solutions to it and D doesn't."
> 
> How is this different from `assert(p != null)` ?

See at top of my reply.




A joke I've been making at BeerConf atm (more or less):

User: Press F5
User: Press F5
User: Press F5, WHY ISN'T THE ABOUT PAGE SHOWING??????
User: Press F5 * 1000

Developer: Why are all the web server instances down?
Developer: Oh a segfault due to null dereference

User: Press F5 * 100000000000

Owner: Why did you use D! If you just used <insert mainstream 
application VM language> we wouldn't have lost millions of dollars!!!


More information about the Digitalmars-d mailing list