int8_t
/uint8_t
is undefined behaviorSection: 29.5.3.1 [rand.req.genl] Status: New Submitter: Peter Dimov Opened: 2024-05-25 Last modified: 2024-05-26
Priority: Not Prioritized
View all other issues in [rand.req.genl].
View all issues with New status.
Discussion:
As pointed out in LWG issue 2326 (closed as NAD) and
on reddit,
instantiating e.g. uniform_int_distribution<uint8_t>
is undefined behavior
because of the requirement 29.5.3.1 [rand.req.genl] bullet (1.5):
-1- Throughout this subclause 29.5 [rand], the effect of instantiating a template:
[…]
(1.4) — that has a template type parameter named
RealType
is undefined unless the corresponding template argument is cv-unqualified and is one offloat
,double
, orlong double
.(1.5) — that has a template type parameter named
IntType
is undefined unless the corresponding template argument is cv-unqualified and is one ofshort
,int
,long
,long long
,unsigned short
,unsigned int
,unsigned long
, orunsigned long long
.(1.6) — that has a template type parameter named
UIntType
is undefined unless the corresponding template argument is cv-unqualified and is one ofunsigned short
,unsigned int
,unsigned long
, orunsigned long long
.
This is, in my opinion, a defect; such uses should either be rejected at compile time (made ill-formed), or permitted (as 2326 proposes.)
UB here has undesirable safety implications, because it's possible to
write code that produces a random, or a seemingly random, sequence
of uint8_t
numbers on platform A, but an arbitrarily non-random
sequence on platform B (e.g. all zeroes.)
If that sequence is then used in e.g. a cryptographic algorithm, bad things will happen on platform B, and the tests on platform A won't catch the issue.
[2024-05-26; Daniel comments]
I think that all violations of the bullets 29.5.3.1 [rand.req.genl] (1.4), (1.5), and (1.6)
are missed opportunities of Mandates (That is: Make the program ill-formed), because
they can be all checked (easily) at compile-time, regardless whether we agree on
the question to support int8_t
/uint8_t
(Violations of (1.1), (1.2), and (1.3)
still have to be remain undefined because of additional runtime requirements imposed).
Given that I also think that we should consider to either normatively extend all of (1.4), (1.5), and (1.6) to corresponding extended floating point types and extended (unsigned) integer types, or to the minimum make these extended types conditionally-supported with implementation-defined semantics (A word of power that is used at several places).
Proposed resolution:
This wording is relative to N4981.
[Drafting Note: Two mutually exclusive options are prepared, depicted below by Option A and Option B, respectively.]
Option A: As suggested in issue LWG 2326
Modify 29.5.3.1 [rand.req.genl] as indicated:
-1- Throughout this subclause 29.5 [rand], the effect of instantiating a template:
[…]
(1.4) — that has a template type parameter named
RealType
is undefined unless the corresponding template argument is cv-unqualified and is one offloat
,double
, orlong double
.(1.5) — that has a template type parameter named
IntType
is undefined unless the corresponding template argument is cv-unqualified and is a standard integer type (6.8.2 [basic.fundamental])one of.short
,int
,long
,long long
,unsigned short
,unsigned int
,unsigned long
, orunsigned long long
(1.6) — that has a template type parameter named
UIntType
is undefined unless the corresponding template argument is cv-unqualified and is a standard unsigned integer type (6.8.2 [basic.fundamental])one of.unsigned short
,unsigned int
,unsigned long
, orunsigned long long
Option B: Make ill-formed.
Modify 29.5.3.1 [rand.req.genl] as indicated:
-1- Throughout this subclause 29.5 [rand], the effect of instantiating a template:
[…]
(1.4) — that has a template type parameter named
RealType
is undefined unless the corresponding template argument is cv-unqualified and is one offloat
,double
, orlong double
.(1.5) — that has a template type parameter named
IntType
renders the program ill-formedis undefinedunless the corresponding template argument is cv-unqualified and is one ofshort
,int
,long
,long long
,unsigned short
,unsigned int
,unsigned long
, orunsigned long long
.(1.6) — that has a template type parameter named
UIntType
renders the program ill-formedis undefinedunless the corresponding template argument is cv-unqualified and is one ofunsigned short
,unsigned int
,unsigned long
, orunsigned long long
.