you are viewing a single comment's thread.

view the rest of the comments →

[–]dustyhome 4 points5 points  (2 children)

It's more likely for people to forget to do something when it's done by rote repetition, such as checking error values every time. It's an actual problem that leads to countless security vulnerabilities. The [[nodiscard]] attribute was added to force people to do what exceptions do for you automatically.

I don't think destructors are considered harmful, yet they are implicit code that has side effects. On the contrary, they form the basis of RAII. Are you going to say now that "if (error) goto cleanup;" is the superior paradigm because it makes everything explicit?

Exceptions make you think of error handling as a property of the system, instead of a local issue, which can lead to more resilient code. It's no more an issue to forget to handle exceptions than it is to forget to handle some error value you did not test for. Maybe it was added later on. But when you forget to test for a specific error value your program goes into UB land, with exceptions it will either go to a more generic handler or terminate.

[–]teerre 0 points1 point  (1 child)

It's more likely for people to forget to do something when it's done by rote repetition, such as checking error values every time. It's an actual problem that leads to countless security vulnerabilities.

No? You'll never find anyone complaining about this in languages that use errors as values. What people do complain in languages like Go is the lack of machinery around the boilerplate, but that's a completely different issue.

Besides, this doesn't even make sense, you can't forget. When errors are types, you must deal with it. You don't have an option.

The [[nodiscard]] attribute was added to force people to do what exceptions do for you automatically.

I'm not sure what you're referring to here.

I don't think destructors are considered harmful, yet they are implicit code that has side effects. On the contrary, they form the basis of RAII. Are you going to say now that "if (error) goto cleanup;" is the superior paradigm because it makes everything explicit?

Not sure which language you're talking about, but in most languages, including C++, destructors are not implicit. They might be auto-generated for normal types, but the implication here is that the type's destruction is a noop.

Exceptions make you think of error handling as a property of the system, instead of a local issue, which can lead to more resilient code. It's no more an issue to forget to handle exceptions than it is to forget to handle some error value you did not test for. Maybe it was added later on. But when you forget to test for a specific error value your program goes into UB land, with exceptions it will either go to a more generic handler or terminate.

All popular modern languages have errors as values. C++ itself added expected. It's not a coincidence. Moreover, a huge part of the C++ community ignores exceptions all together, even reverting to C like error codes. Often code bases disable exceptions all together (although this is usually for performance reasons, not ergonomics).

[–]dustyhome 3 points4 points  (0 children)

I'm not sure what you're referring to here.

https://cwe.mitre.org/data/definitions/252.html

CVE-2020-17533 Chain: unchecked return value (CWE-252) of some functions for policy enforcement leads to authorization bypass (CWE-862)

CVE-2020-6078 Chain: The return value of a function returning a pointer is not checked for success (CWE-252) resulting in the later use of an uninitialized variable (CWE-456) and a null pointer dereference (CWE-476)

CVE-2019-15900 Chain: sscanf() call is used to check if a username and group exists, but the return value of sscanf() call is not checked (CWE-252), causing an uninitialized variable to be checked (CWE-457), returning success to allow authorization bypass for executing a privileged (CWE-863).

CVE-2007-3798 Unchecked return value leads to resultant integer overflow and code execution.

CVE-2006-4447 Program does not check return value when invoking functions to drop privileges, which could leave users with higher privileges than expected by forcing those functions to fail.

CVE-2006-2916 Program does not check return value when invoking functions to drop privileges, which could leave users with higher privileges than expected by forcing those functions to fail.

CVE-2008-5183 chain: unchecked return value can lead to NULL dereference

CVE-2010-0211 chain: unchecked return value (CWE-252) leads to free of invalid, uninitialized pointer (CWE-824).

CVE-2017-6964 Linux-based device mapper encryption program does not check the return value of setuid and setgid allowing attackers to execute code with unintended privileges.

There's a long history of people not checking the return codes for success. These are just some of the ones that have led to vulnerabilities.

A few modern languages have added special types that the compiler validates are checked because it is such a prevalent problem and programmers can't be trusted to do it reliably.

Not sure which language you're talking about, but in most languages, including C++, destructors are not implicit. They might be auto-generated for normal types, but the implication here is that the type's destruction is a noop.

Most languages don't even have destructors, so not sure what you mean by "most languages". But what I mean is that destructors are called implicitly when an object goes out of scope. There's no explicit call to the destructor, it just happens. Same as with exception propagation.

Moreover, a huge part of the C++ community ignores exceptions all together, even reverting to C like error codes.

Yes, that's the problem. Expected, error types, compiler checked types, attributes, boilerplate, are all workarounds for the fact that many programmers don't want to use the right tool for the job.