Ensure signed integer type for stse_ReturnCode_t enum#85
Conversation
Mark the read-only buffers as `const` in `xxx_ecc_verify_signature()` to reflect that the input buffer is not modified. This improves const-correctness and clarifies the API contract.
…om hibernate state due polling)
Add `__STSE_SIGNED = -1` as the last enum value to guarantee that `stse_ReturnCode_t` is treated as a signed integer type across all compilers. This allows printing enum values using the `%d` format specifier reliably on all platforms.
stse_ReturnCode_t enum
|
Hello @parmi93, Thanks for your contribution, and sorry for the delayed review. I completely agree with your portability concerns regarding how enums are handled in printf. However, instead of forcing the compiler to treat stse_ReturnCode_t as a signed integer by default via enum definition hacks, I think the best long-term choice is to explicitly fix the type to a predictable, standard 32-bit size. Since most of our API functions rely on this enum as a direct return type, we are exposing the library's ABI directly to how different compilers choose to interpret and optimize that enum. If you look at industry-standard cryptographic APIs (like PKCS#11), they completely avoid returning raw enums for this exact reason. Instead, they map return codes to fixed-width integer types in the public header. For example: typedef int32_t stse_ReturnCode_t; // The type is explicitly a 32-bit signed integer
#define STSE_OK ((stse_ReturnCode_t)0)
#define STSE_ERROR ((stse_ReturnCode_t)1)
// Function signature remains perfectly portable
stse_ReturnCode_t stse_init(stse_handler_t * p_stse);Ensuring stse_ReturnCode_t is an explicit int32_t will guarantee identical ABI behavior whether this library is running on an 8-bit MCU or a 64-bit Android/Linux system, while naturally solving the printf issue. I can open a dedicated issue for this architectural change and take care of the refactoring. What do you think? |
|
Hi, thank you for the detailed explanation! I just wanted to point out a couple of things for consideration:
That said, either approach works fine for me, so feel free to go with whichever solution you prefer. It will make debugging slightly more difficult, but I'll manage somehow. |
|
To try getting both of your points, we could add a last enum of this value : 0x7FFFFFFF, to force using 32 bits, and if my understanding is correct, compiler must respect this order when choosing for type :
So with this, since our value fits in a signed int of 32 bits, every compiler should make this variable into the desired type right ? I could find examples of this practice here for reference : https://codebrowser.dev/imgui/imgui/dxsdk/Include/d3d9types.h.html Let me know your thoughts. |
|
After revisiting the C standard, I realised that my proposal of adding C99 §6.7.2.2 ¶1 defines the syntax of an enumeration as:
C99 §6.7.2.2 ¶2 specifies that the result of a constant-expression must be representable as an
C99 §6.7.2.2 ¶3 further states that each enumeration-constant has type
However, C99 §6.7.2.2 ¶4 states that the type chosen for the enumeration itself is implementation-defined:
Therefore, adding In other words, to print an enumeration value portably, an explicit cast remains necessary: stse_ReturnCode_t rc = STSE_OK;
printf("Return code: %d\n", (int)rc);Regarding @nils-cercariolo-st's proposal to add the enumerator value As a result, my original proposal of adding The only practical advantage of defining Therefore, if ABI stability is a concern, I think it is reasonable to define |
This PR adds a sentinel value
__STSE_SIGNED = -1to thestse_ReturnCode_tenum to guarantee that the enum is always treated as a signed integer type across all compilers and platforms.Why This Change?
In C, enumerations are implicitly convertible to integers, but the C standard does not mandate whether an enum type should be signed or unsigned. The actual underlying type depends on:
The Problem
Without this fix, users cannot write portable code to print
stse_ReturnCode_tvalues. Depending on the platform and compiler,%umay be required on some systems while%dis needed on others, resulting in non-portable and potentially buggy code.Without this fix, code like:
Could behave inconsistently:
%dgives incorrect output (user should use%u)%dgives correct outputThe Solution
By adding
__STSE_SIGNED = -1as the last enum value, we force the compiler to choose a signed integer type (since the enum now contains a negative value that must be representable).This guarantees:
%dformat specifier for printing enum valuesTechnical Details
Per C99/C11 standards, the underlying type of an enum is implementation-defined but must be capable of representing all enumerator values. By including a negative value, we ensure the enum's underlying type is signed integer, making
printf()with%dportable and safe.