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

Check assumptions on integer implementation at compile time #798

Merged
merged 2 commits into from
Aug 16, 2020

Conversation

sipa
Copy link
Contributor

@sipa sipa commented Aug 13, 2020

A compile-time check is implemented in a new src/assumptions.h which verifies several aspects that are implementation-defined in C:

  • size of bytes
  • conversion between unsigned and (negative) signed types
  • right-shifts of negative signed types.

@sipa
Copy link
Contributor Author

sipa commented Aug 13, 2020

It seems fairly easy to turn this into a compile time check, by using (that_expression - 1) as the size of array.

However, maybe we want to include endianness into the check, and I'm not sure that can be done at compile time.

@gmaxwell
Copy link
Contributor

as the size of array.

Var arrays are C99 and "optional" in later standards and not supported by MSVC.

@sipa
Copy link
Contributor Author

sipa commented Aug 13, 2020

@gmaxwell Yes, but this isn't relying on vararrays - the expression is a compile-time constant.

In fact, it has to be constant. A vararray of negative size could compile. So you have to do something like define a struct with a member array (where a vararray isn't allowed).

@sipa
Copy link
Contributor Author

sipa commented Aug 13, 2020

@gmaxwell this seems to work in gcc/clang/icc/msvc: https://godbolt.org/z/6dsar5

@gmaxwell
Copy link
Contributor

Yeah, I tested it with GCC 2.95 on i386 and tinyc and it seems to be happy there too. One downside is that when it fails you get an extremely opaque error.

@sipa sipa force-pushed the 202008_assumptions branch 2 times, most recently from 8be2c47 to dd00182 Compare August 13, 2020 06:38
@sipa
Copy link
Contributor Author

sipa commented Aug 13, 2020

Added conversions from signed to signed, and a check for CHAR_BIT. Anything else? Do we have any unusual assumptions on the size of int etc?

@real-or-random
Copy link
Contributor

@sipa Are you aware of #792 ? :P

@real-or-random
Copy link
Contributor

One downside is that when it fails you get an extremely opaque error.

We could use static_assert if it's supported by the compiler but I don't think it's worth the additional #ifdefs. These errors should be super rare, so it's acceptable that they're somewhat opaque. And it's probably better to have a compiler error instead of a runtime error.

I read up a little bit on these techniques. The issues with VLAs was something else: In some cases this array trick silently didn't do anything when the expression is non-constant, e.g., when you have a compiler like GCC that supports VLAs as an extension and you happen to pass a non-constant value, then it can't be a compiler error even if the size is negative. This hit the Linux kernel for example.

But what we do here is robust against this failure mode because VLAs are never supported on a file level / global scope. I verified this in godbolt. Even GCC errors out if you pass a non-constant value. (Clang fails at another stage but the message is pretty harsh: fields must have a constant size: 'variable length array in structure' extension will never be supported :D) The difference in the Linux kernel is probably that they don't want to collect all the assumptions in a single place and they want a statement instead.

Approach ACK

Maybe we want to move the assumptions to a separate header like in Bitcoin Core (https://github.com/bitcoin/bitcoin/blob/master/src/compat/assumptions.h). That's cleaner and it's easier to point people to the file, e.g., in the README.

@gmaxwell
Copy link
Contributor

A separate file might make it marginally more likely to get a more useful error message (e.g. telling you what file it was in) from more compilers.

@sipa
Copy link
Contributor Author

sipa commented Aug 13, 2020

A separate file might make it marginally more likely to get a more useful error message (e.g. telling you what file it was in) from more compilers.

That's a good point.

Moved.

@gmaxwell
Copy link
Contributor

You might want to a comment above it that says something like:

/* This library, like most software, relies on a number of compiler implementation defined (not undefined) behaviours. Although the behaviours we require are essentially universal we test them specifically here to reduce the odds of experiencing an unwelcome surprise. */

@sipa
Copy link
Contributor Author

sipa commented Aug 13, 2020

@gmaxwell Added.

src/assumptions.h Outdated Show resolved Hide resolved
@gmaxwell
Copy link
Contributor

Include it in gen_context.c too. Sorry for dribbling changes.

@sipa
Copy link
Contributor Author

sipa commented Aug 13, 2020

Done. Also added to bench_internal.c, tests_exhaustive.c, and valgrind_ctime_test.c.

@gmaxwell
Copy link
Contributor

ACK fdb6dbc

@sipa sipa changed the title Check assumptions on integer implementation at runtime Check assumptions on integer implementation at compile time Aug 14, 2020
Copy link
Contributor

@real-or-random real-or-random left a comment

Choose a reason for hiding this comment

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

Added conversions from signed to signed, and a check for CHAR_BIT. Anything else? Do we have any unusual assumptions on the size of int etc?

ACK except nit. We should then add more assumptions from #792 later.

src/assumptions.h Outdated Show resolved Hide resolved
@sipa
Copy link
Contributor Author

sipa commented Aug 15, 2020

@real-or-random Sounds good.

@gmaxwell
Copy link
Contributor

ACK 7c06899

@real-or-random
Copy link
Contributor

ACK 7c06899 code review and tested

@real-or-random real-or-random merged commit 670cdd3 into bitcoin-core:master Aug 16, 2020
jasonbcox pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Sep 29, 2020
Summary:
 * Add support for (signed) __int128

 * Compile-time check assumptions on integer types

This is a backport of secp256k1 [[bitcoin-core/secp256k1#798 | PR798]]

Test Plan:
  ninja check-secp256k1

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Differential Revision: https://reviews.bitcoinabc.org/D7632
deadalnix pushed a commit to Bitcoin-ABC/secp256k1 that referenced this pull request Sep 30, 2020
Summary:
 * Add support for (signed) __int128

 * Compile-time check assumptions on integer types

This is a backport of secp256k1 [[bitcoin-core/secp256k1#798 | PR798]]

Test Plan:
  ninja check-secp256k1

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Differential Revision: https://reviews.bitcoinabc.org/D7632
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants