Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Remove C-style const-violating cast, Use reinterpret_cast #28127

Merged
merged 3 commits into from Jul 26, 2023

Conversation

maflcko
Copy link
Member

@maflcko maflcko commented Jul 22, 2023

Using a C-style cast to convert pointer types to a byte-like pointer type has many issues:

  • It may accidentally and silently throw away const.
  • It forces reviewers to check that it doesn't accidentally throw away const.

For example, on current master a const char* is cast to unsigned char* (without const), see

inline const unsigned char* UCharCast(const char* c) { return (unsigned char*)c; }
. This can lead to UB, and the only reason why it didn't lead to UB is because the return type added back the const. (Obviously this would break if the return type was deduced via auto)

Fix all issues by adding back the const and using reinterpret_cast where appropriate.

@DrahtBot
Copy link
Contributor

DrahtBot commented Jul 22, 2023

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK hebasto, darosior, john-moffett
Concept ACK jonatack

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

@hebasto
Copy link
Member

hebasto commented Jul 22, 2023

Using a C-style cast to convert pointer types to a byte-like pointer type has many issues

Can clang-tidy or other tools be helpful in catching such cases in the future?

@emc99
Copy link

emc99 commented Jul 22, 2023

Using a C-style cast to convert pointer types to a byte-like pointer type has many issues:

  • It may accidentally and silently throw away const.
  • It forces reviewers to check that it doesn't accidentally throw away const.

For example, on current master a const char* is cast to unsigned char* (without const), see

inline const unsigned char* UCharCast(const char* c) { return (unsigned char*)c; }

. This can lead to UB, and the only reason why it didn't lead to UB is because the return type added back the const. (Obviously this would break if the return type was deduced via auto)
Fix all issues by adding back the const and using reinterpret_cast where appropriate.

What does 'UB' stand for? Something-Breakage?

@sipa
Copy link
Member

sipa commented Jul 22, 2023

UB = Undefined behavior

@jonatack
Copy link
Contributor

Concept ACK

@maflcko
Copy link
Member Author

maflcko commented Jul 24, 2023

Can clang-tidy or other tools be helpful in catching such cases in the future?

Yeah, you can use cppcoreguidelines-pro-type-cstyle-cast if you want. But that will produce some more warnings in places where a const is intentionally and correctly removed. Also, it will warn in some places that should use a Span instead. However, I think using Span in more places or other fixes can be left for follow-ups.


#include <compat/endian.h>

uint16_t static inline ReadLE16(const unsigned char* ptr)
{
uint16_t x;
memcpy((char*)&x, ptr, 2);
memcpy(reinterpret_cast<char*>(&x), ptr, 2);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why casting in the first place since memcpy would reinterpret it as unsigned char * anyways?

@hebasto
Copy link
Member

hebasto commented Jul 24, 2023

Concept ACK.

@maflcko maflcko changed the title Remove C-style const-violating cast, Use reinterpret_cast refactor: Remove C-style const-violating cast, Use reinterpret_cast Jul 24, 2023
@hebasto
Copy link
Member

hebasto commented Jul 24, 2023

UPD. Removed comment. nm

@maflcko
Copy link
Member Author

maflcko commented Jul 24, 2023

Is this unused as well:

No? begin() returns a const iterator on the mutable keyChild. The cast is needed to remove the wrongly added const. As said previously, this is out-of-scope for this pull request: #28127 (comment)

Copy link
Member

@hebasto hebasto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK fa474bc, I have reviewed the code and it looks OK.

Copy link
Member

@darosior darosior left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK fa474bc. This makes sense and looks good to me, though i'm far from a language lawyer.

nit: the first two commits share the same objective and title and could thus be squashed.

@hebasto
Copy link
Member

hebasto commented Jul 24, 2023

As a follow up, I'm pretty sure that all casts of ArgsManager::ParseParameters's arguments in test/argsman_tests.cpp can be just dropped as well.

MarcoFalke added 3 commits July 24, 2023 15:32
Seems confusing and brittle to remove const and then add it back in the
return type.
Also, wrap reinterpret_cast into a CharCast to ensure it is only called
on byte pointers.
@maflcko
Copy link
Member Author

maflcko commented Jul 24, 2023

Thanks, addressed both comments by reviewers.

Copy link
Member

@hebasto hebasto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re-ACK fa9108f.

@DrahtBot DrahtBot requested a review from darosior July 24, 2023 16:26
@darosior
Copy link
Member

re-utACK fa9108f

@DrahtBot DrahtBot removed the request for review from darosior July 24, 2023 16:28
Copy link
Contributor

@john-moffett john-moffett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK fa9108f

@fanquake fanquake merged commit f57e724 into bitcoin:master Jul 26, 2023
15 checks passed
@maflcko maflcko deleted the 2307-no-const-cast- branch July 26, 2023 15:06
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Aug 9, 2023
…se reinterpret_cast

fa9108f refactor: Use reinterpret_cast where appropriate (MarcoFalke)
3333f95 refactor: Avoid casting away constness (MarcoFalke)
fa6394d refactor: Remove unused C-style casts (MarcoFalke)

Pull request description:

  Using a C-style cast to convert pointer types to a byte-like pointer type has many issues:

  * It may accidentally and silently throw away `const`.
  * It forces reviewers to check that it doesn't accidentally throw away `const`.

  For example, on current master a `const char*` is cast to `unsigned char*` (without `const`), see https://github.com/bitcoin/bitcoin/blob/d23fda05842ba4539b225bbab01b94df0060f697/src/span.h#L273 . This can lead to UB, and the only reason why it didn't lead to UB is because the return type added back the `const`. (Obviously this would break if the return type was deduced via `auto`)

  Fix all issues by adding back the `const` and using `reinterpret_cast` where appropriate.

ACKs for top commit:
  darosior:
    re-utACK fa9108f
  hebasto:
    re-ACK fa9108f.
  john-moffett:
    ACK fa9108f

Tree-SHA512: 87f6e4b574f9bd96d4e0f2a0631fd0a9dc6096e5d4f1b95042fe9f197afc2fe9a24e333aeb34fed11feefcdb184a238fe1ea5aff10d580bb18d76bfe48b76a10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants