|
192 | 192 | * Loop 3 — performs the actual decryption into the buffer and binds |
193 | 193 | * var; its UPDATE clears the flag so loops 1 and 2 also exit. |
194 | 194 | * |
195 | | - * The encrypted blob is an inline compound literal in read-only storage. |
| 195 | + * The encrypted blob is a static const array in read-only storage. |
196 | 196 | * The plaintext buffer lives only while the body executes. |
197 | 197 | * |
198 | 198 | * Lifetime note: do NOT use var outside the braces. */ |
199 | 199 | #define OBF_WITH(var, s) \ |
| 200 | + (void)sizeof(struct { \ |
| 201 | + _Static_assert(sizeof(s) <= (size_t)(OBF_MAX_LEN), \ |
| 202 | + "OBF_WITH: string length exceeds OBF_MAX_LEN"); \ |
| 203 | + char obf_sa_; \ |
| 204 | + }); \ |
| 205 | + static const unsigned char var##__blob_[] = { \ |
| 206 | + OBF_SBOX(OBF_SEED0), OBF_SBOX(OBF_SEED1), \ |
| 207 | + OBF_SBOX(OBF_SEED2), OBF_SBOX(OBF_SEED3), \ |
| 208 | + OBF_ENC_ALL(s) \ |
| 209 | + }; \ |
200 | 210 | for (int var##__once_ = 1; var##__once_; var##__once_ = 0) \ |
201 | 211 | for (unsigned char var##__buf_[OBF_MAX_LEN] = {0}; \ |
202 | 212 | var##__once_; \ |
203 | 213 | obf_zero(var##__buf_, (size_t)OBF_MAX_LEN), var##__once_ = 0) \ |
204 | | - for (const char *var = ( \ |
205 | | - (void)sizeof(struct { \ |
206 | | - _Static_assert(sizeof(s) <= (size_t)(OBF_MAX_LEN), \ |
207 | | - "OBF_WITH: string length exceeds OBF_MAX_LEN"); \ |
208 | | - char obf_sa_; \ |
209 | | - }), \ |
210 | | - obf_decrypt( \ |
211 | | - (const unsigned char[]){ \ |
212 | | - OBF_SBOX(OBF_SEED0), OBF_SBOX(OBF_SEED1), \ |
213 | | - OBF_SBOX(OBF_SEED2), OBF_SBOX(OBF_SEED3), \ |
214 | | - OBF_ENC_ALL(s) \ |
215 | | - }, \ |
216 | | - (size_t)(sizeof(s) + 4u), var##__buf_) \ |
217 | | - ); \ |
| 214 | + for (const char *var = obf_decrypt( \ |
| 215 | + var##__blob_, \ |
| 216 | + (size_t)(sizeof(s) + 4u), var##__buf_); \ |
218 | 217 | var##__once_; var##__once_ = 0) |
219 | 218 |
|
220 | 219 | /* ── OBF_INT ───────────────────────────────────────────────────────── |
|
336 | 335 | "OBF_STRING: string length exceeds OBF_MAX_LEN"); \ |
337 | 336 | char obf_sa_; \ |
338 | 337 | }); \ |
| 338 | + static const unsigned char var##__blob_[] = { \ |
| 339 | + OBF_SBOX(OBF_SEED0), OBF_SBOX(OBF_SEED1), \ |
| 340 | + OBF_SBOX(OBF_SEED2), OBF_SBOX(OBF_SEED3), \ |
| 341 | + OBF_ENC_ALL(s) \ |
| 342 | + }; \ |
339 | 343 | unsigned char var##__buf_[OBF_MAX_LEN] = {0}; \ |
340 | 344 | unsigned char *var##__gc_ \ |
341 | 345 | __attribute__((cleanup(obf_buf_cleanup_))) = var##__buf_; \ |
342 | | - const char *var = obf_decrypt( \ |
343 | | - (const unsigned char[]){OBF_SBOX(OBF_SEED0), OBF_SBOX(OBF_SEED1), \ |
344 | | - OBF_SBOX(OBF_SEED2), OBF_SBOX(OBF_SEED3), \ |
345 | | - OBF_ENC_ALL(s)}, \ |
346 | | - (size_t)(sizeof(s) + 4u), var##__buf_); \ |
| 346 | + const char *var = obf_decrypt(var##__blob_, \ |
| 347 | + (size_t)(sizeof(s) + 4u), var##__buf_); \ |
347 | 348 | (void)var##__gc_ |
348 | 349 |
|
349 | 350 | #else /* MSVC / unknown: no auto-zero; use OBF_WITH for safe cleanup */ |
|
354 | 355 | "OBF_STRING: string length exceeds OBF_MAX_LEN"); \ |
355 | 356 | char obf_sa_; \ |
356 | 357 | }); \ |
| 358 | + static const unsigned char var##__blob_[] = { \ |
| 359 | + OBF_SBOX(OBF_SEED0), OBF_SBOX(OBF_SEED1), \ |
| 360 | + OBF_SBOX(OBF_SEED2), OBF_SBOX(OBF_SEED3), \ |
| 361 | + OBF_ENC_ALL(s) \ |
| 362 | + }; \ |
357 | 363 | unsigned char var##__buf_[OBF_MAX_LEN] = {0}; \ |
358 | | - const char *var = obf_decrypt( \ |
359 | | - (const unsigned char[]){OBF_SBOX(OBF_SEED0), OBF_SBOX(OBF_SEED1), \ |
360 | | - OBF_SBOX(OBF_SEED2), OBF_SBOX(OBF_SEED3), \ |
361 | | - OBF_ENC_ALL(s)}, \ |
| 364 | + const char *var = obf_decrypt(var##__blob_, \ |
362 | 365 | (size_t)(sizeof(s) + 4u), var##__buf_) |
363 | 366 |
|
364 | 367 | #endif /* __GNUC__ || __clang__ */ |
|
0 commit comments