|
56 | 56 |
|
57 | 57 | #define STRING_LENGTH_WITH_SUFFIX(length_a, suffix) (length_a - /* string terminator of string a */ 1 + sizeof(suffix))
|
58 | 58 |
|
59 |
| -#define STRUCT_MEMBER_SIZE(struct_type, member) (sizeof(((struct_type *) 0)->member)) |
| 59 | +#define STRUCT_MEMBER_SIZE(struct_type, member) (sizeof(((struct_type *) NULL)->member)) |
60 | 60 |
|
61 | 61 | /**
|
62 | 62 | * Copy data of fixed size to a destination of fixed size. This macro performs a static assertion at compile time, that
|
|
73 | 73 | memcpy(destination, source, sizeof(source)); \
|
74 | 74 | })
|
75 | 75 |
|
| 76 | +#define POINTER_SIZE (sizeof(void *)) |
| 77 | +/** |
| 78 | + * Get the offset of a pointer from 32bit based memory alignment. Memory access of pointers to data types larger than |
| 79 | + * one byte need to be aligned to 32bit words / POINTER_SIZE (or 16bit for shorts, which we don't handle separately here |
| 80 | + * and always use 32bit alignment), as required by Ledger Nano S's hardware, and for other devices by the compiler flags |
| 81 | + * (presumably, as other devices do in fact support non-aligned memory access, however without memory alignment, the app |
| 82 | + * froze on the unaligned memset in review_entries_launch_use_case_review since using the SDK's Makefile.standard_app |
| 83 | + * for building as of 5542f4b6, but not before that change. I did not further investigate, which exact flag introduced |
| 84 | + * the issue, or whether maybe the accessed pointer was 32bit aligned before that change by coincidence). Note that the |
| 85 | + * speculos emulator does not enforce any memory alignment, which is why related issues do not show there. |
| 86 | + * In any case, it's a good idea to conform to memory alignment. |
| 87 | + */ |
| 88 | +#define POINTER_MEMORY_ALIGNMENT_OFFSET(pointer) (((uintptr_t) pointer) % POINTER_SIZE) |
| 89 | + |
| 90 | +/** |
| 91 | + * Declare a pointer of given type within G_io_apdu_buffer for temporary use, while G_io_apdu_buffer is not otherwise |
| 92 | + * used or accessed. The pointer is ensured to be memory aligned, see POINTER_MEMORY_ALIGNMENT_OFFSET, and its type is |
| 93 | + * checked to fit G_io_apdu_buffer. |
| 94 | + */ |
| 95 | +#define DECLARE_TEMPORARY_G_IO_APDU_BUFFER_POINTER(pointer_type, variable_name) \ |
| 96 | + _Static_assert( \ |
| 97 | + /* The memory alignment offset can not be statically computed at compile time, therefore we assume for the */ \ |
| 98 | + /* static assertion that the largest padding POINTER_SIZE - 1 has to be applied. */ \ |
| 99 | + sizeof(*((pointer_type) NULL)) <= sizeof(G_io_apdu_buffer) - (POINTER_SIZE - 1), \ |
| 100 | + "Pointer type does not fit G_io_apdu_buffer\n" \ |
| 101 | + ); \ |
| 102 | + pointer_type variable_name = (pointer_type) ( \ |
| 103 | + G_io_apdu_buffer + \ |
| 104 | + ( \ |
| 105 | + POINTER_MEMORY_ALIGNMENT_OFFSET(G_io_apdu_buffer) \ |
| 106 | + ? POINTER_SIZE - POINTER_MEMORY_ALIGNMENT_OFFSET(G_io_apdu_buffer) \ |
| 107 | + : 0 \ |
| 108 | + ) \ |
| 109 | + ); |
| 110 | + |
76 | 111 | #endif // _NIMIQ_UTILITY_MACROS_H_
|
0 commit comments