diff --git a/src/ext/equix/hashx/src/compiler.h b/src/ext/equix/hashx/src/compiler.h index f248e8c1ea..b7b47dfcb5 100644 --- a/src/ext/equix/hashx/src/compiler.h +++ b/src/ext/equix/hashx/src/compiler.h @@ -27,12 +27,51 @@ HASHX_PRIVATE bool hashx_compile_a64(const hashx_program* program, uint8_t* code HASHX_PRIVATE void hashx_compiler_init(hashx_ctx* compiler); HASHX_PRIVATE void hashx_compiler_destroy(hashx_ctx* compiler); -#define COMP_PAGE_SIZE 4096 -#define COMP_RESERVE_SIZE 1024 -#define COMP_AVG_INSTR_SIZE 5 -#define COMP_CODE_SIZE \ - ALIGN_SIZE( \ - HASHX_PROGRAM_MAX_SIZE * COMP_AVG_INSTR_SIZE + COMP_RESERVE_SIZE, \ - COMP_PAGE_SIZE) +/* Compiled code sizes in bytes: + * + * Prologue Epilogue MulH Reg-Reg Reg-Imm32 Branch+Tgt MaxInst + * X86 69 64 9 3..4 7 15 10 (br) + * A64 40 36 4 4 12 24 24 (br) + * + * Maximum code sizes, assuming an arbitrary instruction mix including unlimited + * branch instructions. (Branch size * 512 + prologue + epilogue) + * + * Max possible code size (any instructions) + * X86 5253 + * A64 12364 + * + * Actual code sizes tend to be much smaller due to the instruction mix chosen + * by the program generator. To get a quick overview of the statistics, we + * measure the sample mean and sample standard deviation for 1 million random + * hash programs: + * + * Mean Std Deviation 4096 bytes at + * X86 2786.4 26.259 49.9 standard deviations + * A64 3507.7 58.526 10.1 standard deviations + * + * If we search for PRNG sequences that maximize generated code size, it's easy + * to find aarch64 code that needs in the range of 4100-4300 bytes. On x86, this + * search still doesn't turn up programs anywhere close to a full page. + * + * Anyway, this is all to say that a one-page buffer is fine except for in + * extremely rare cases on aarch64, and a two-page buffer is enough for any + * behavior we can expect from the program generator under arbitrary input, + * but only a 4-page buffer is enough for fully arbitrary instruction streams + * on any architecture. + * + * Let's use a 2-page buffer on aarch64, or 1-page elsewhere. + * + * Note that the buffer allocation is done by platform-independent code, + * so COMP_CODE_SIZE must always have a valid size even on platforms where + * it is not actually supported or used. + * + * If this buffer fills up, compilation will fail with a runtime error. + */ + +#ifdef HASHX_COMPILER_A64 +#define COMP_CODE_SIZE (4096 * 2) +#else +#define COMP_CODE_SIZE (4096 * 1) +#endif #endif diff --git a/src/ext/equix/hashx/src/compiler_a64.c b/src/ext/equix/hashx/src/compiler_a64.c index 2e286b3099..f4efa561b9 100644 --- a/src/ext/equix/hashx/src/compiler_a64.c +++ b/src/ext/equix/hashx/src/compiler_a64.c @@ -23,6 +23,9 @@ #ifdef HASHX_COMPILER_A64 +/* Largest compiled instruction (BRANCH) */ +#define COMP_MAX_INSTR_SIZE 24 + static const uint8_t a64_prologue[] = { 0x07, 0x1c, 0x40, 0xf9, /* ldr x7, [x0, #56] */ 0x06, 0x18, 0x40, 0xf9, /* ldr x6, [x0, #48] */ @@ -56,6 +59,8 @@ bool hashx_compile_a64(const hashx_program* program, uint8_t* code) { int creg = -1; EMIT(pos, a64_prologue); for (size_t i = 0; i < program->code_size; ++i) { + if (pos + COMP_MAX_INSTR_SIZE > code + COMP_CODE_SIZE) + return false; const instruction* instr = &program->code[i]; switch (instr->opcode) { @@ -145,6 +150,8 @@ bool hashx_compile_a64(const hashx_program* program, uint8_t* code) { UNREACHABLE; } } + if (pos + sizeof a64_epilogue > code + COMP_CODE_SIZE) + return false; EMIT(pos, a64_epilogue); if (!hashx_vm_rx(code, COMP_CODE_SIZE)) return false; diff --git a/src/ext/equix/hashx/src/compiler_x86.c b/src/ext/equix/hashx/src/compiler_x86.c index 12f59a1d0b..df4fdbebb8 100644 --- a/src/ext/equix/hashx/src/compiler_x86.c +++ b/src/ext/equix/hashx/src/compiler_x86.c @@ -25,6 +25,9 @@ #ifdef HASHX_COMPILER_X86 +/* Largest compiled instruction (BRANCH) */ +#define COMP_MAX_INSTR_SIZE 10 + static const uint8_t x86_prologue[] = { #ifndef WINABI 0x48, 0x89, 0xF9, /* mov rcx, rdi */ @@ -88,6 +91,8 @@ bool hashx_compile_x86(const hashx_program* program, uint8_t* code) { uint8_t* target = NULL; EMIT(pos, x86_prologue); for (size_t i = 0; i < program->code_size; ++i) { + if (pos + COMP_MAX_INSTR_SIZE > code + COMP_CODE_SIZE) + return false; const instruction* instr = &program->code[i]; switch (instr->opcode) { @@ -145,6 +150,8 @@ bool hashx_compile_x86(const hashx_program* program, uint8_t* code) { UNREACHABLE; } } + if (pos + sizeof x86_epilogue > code + COMP_CODE_SIZE) + return false; EMIT(pos, x86_epilogue); return hashx_vm_rx(code, COMP_CODE_SIZE); } diff --git a/src/ext/equix/src/lib.rs b/src/ext/equix/src/lib.rs index 716160b4d5..67232d239c 100644 --- a/src/ext/equix/src/lib.rs +++ b/src/ext/equix/src/lib.rs @@ -376,4 +376,622 @@ mod tests { assert_eq!(ctx.exec(12345).unwrap(), hex!("825a9b6dd5d074af")); assert_eq!(*counter.borrow(), 575); } + + #[test] + fn rng_large_compiler_output() { + // This is really a general HashX test rather than a test for the Rust + // wrapper. It's easier to implement here than in hashx-test, since + // the Rng callback is disabled by default in the cmake build system. + // + // The purpose of this test is to use a specially crafted Rng sequence + // to generate an especially large compiled hash program, to test for + // length-related problems. + // + // There are various ways to generate these Rng sequences. The fuzzer + // in Arti will do this on its own. The sequence here was found with + // a simple ad-hoc optimizer that modifies one byte at a time in a + // search for peaks in either x86_64 or aarch64 code size. + // + // The expected compiled program length: + // + // - On x86_64, 3188 bytes + // (safely less than a page still) + // + // - On aarch64, 4388 bytes + // (would overflow a single page buffer by 292 bytes) + // + + const SEQUENCE: [u64; 558] = [ + 0xffffffffffffffff, // 0 + 0xffffffffffffffff, // 1 + 0xfbfefefbfbfeffff, // 2 + 0xffffffffffffffff, // 3 + 0xffffffffffffffff, // 4 + 0xfffffffffffffdff, // 5 + 0xffffffffffffffff, // 6 + 0xffffffffffffffff, // 7 + 0xfffffffefffffffd, // 8 + 0xffffffffffffffff, // 9 + 0xffffffffffffffff, // 10 + 0xffffffffffffffff, // 11 + 0xfefffffeffffffff, // 12 + 0xffffffffffffffff, // 13 + 0xffffffffffffffff, // 14 + 0xfefbfcfdfefffefb, // 15 + 0xfffffffffffffffc, // 16 + 0xffffffffffffffff, // 17 + 0xffffffffffffffff, // 18 + 0xffffffffffffffff, // 19 + 0xffffffffffffffff, // 20 + 0xfffffffffffefffe, // 21 + 0xfffffefffbfefbfe, // 22 + 0xffffffffffffffff, // 23 + 0xfefeffffffffffff, // 24 + 0xffffffffffffffff, // 25 + 0xffffffffffffffff, // 26 + 0xffffffffffffffff, // 27 + 0xffffffffffffffff, // 28 + 0xffffffffffffffff, // 29 + 0xffffffffffffffff, // 30 + 0xffffffffffffffff, // 31 + 0xffffffffffffffff, // 32 + 0xffffffffffffffff, // 33 + 0xfffffffeffffffff, // 34 + 0xffffffffffffffff, // 35 + 0xfffffffffffffffe, // 36 + 0xffffffffffffffff, // 37 + 0xfbfbfffefffbffff, // 38 + 0xffffffffffffffff, // 39 + 0xfffffffffffffffe, // 40 + 0xffffffffffffffff, // 41 + 0xffffffffffffffff, // 42 + 0xffffffffffffffff, // 43 + 0xffffffffffffffff, // 44 + 0xfffffffeffffffff, // 45 + 0xffffffffffffffff, // 46 + 0xffffffffffffffff, // 47 + 0xffffffffffffffff, // 48 + 0xfefefffdffffffff, // 49 + 0xfefbfefefefcfdff, // 50 + 0xffffffffffffffff, // 51 + 0xffffffffffffffff, // 52 + 0xffffffffffffffff, // 53 + 0xffffffffffffffff, // 54 + 0xfefffffffefefffc, // 55 + 0xfffffffeffffffff, // 56 + 0xfbfefffefbfefefb, // 57 + 0xfffffffeffffffff, // 58 + 0xffffffffffffffff, // 59 + 0xfffffffffffffefc, // 60 + 0xfffffffffffffffc, // 61 + 0xffffffffffffffff, // 62 + 0xffffffffffffffff, // 63 + 0xffffffffffffffff, // 64 + 0xfffffefdffffffff, // 65 + 0xffffffffffffffff, // 66 + 0xffffffffffffffff, // 67 + 0xffffffffffffffff, // 68 + 0xfefbfefbfefbfbfe, // 69 + 0xffffffffffffffff, // 70 + 0xffffffffffffffff, // 71 + 0xfffefeffffffffff, // 72 + 0xfffffffffffffffe, // 73 + 0xffffffffffffffff, // 74 + 0xffffffffffffffff, // 75 + 0xfeffffffffffffff, // 76 + 0xffffffffffffffff, // 77 + 0xffffffffffffffff, // 78 + 0xffffffffffffffff, // 79 + 0xffffffffffffffff, // 80 + 0xffffffffffffffff, // 81 + 0xfffffffefcfdfeff, // 82 + 0xffffffffffffffff, // 83 + 0xfefeffffffffffff, // 84 + 0xffffffffffffffff, // 85 + 0xffffffffffffffff, // 86 + 0xffffffffffffffff, // 87 + 0xfffffffdffffffff, // 88 + 0xffffffffffffffff, // 89 + 0xffffffffffffffff, // 90 + 0xffffffffffffffff, // 91 + 0xfefbfffefefbfbfe, // 92 + 0xffffffffffffffff, // 93 + 0xfffffffeffffffff, // 94 + 0xfffffffffefeffff, // 95 + 0xffffffffffffffff, // 96 + 0xfffffffffffffffe, // 97 + 0xffffffffffffffff, // 98 + 0xffffffffffffffff, // 99 + 0xffffffffffffffff, // 100 + 0xfffffffffffffffe, // 101 + 0xfffffffffeffffff, // 102 + 0xfdfdffffffffffff, // 103 + 0xfbfefbfefefefefe, // 104 + 0xffffffffffffffff, // 105 + 0xffffffffffffffff, // 106 + 0xfffffffffffffffd, // 107 + 0xfefffffffffefdff, // 108 + 0xfffffffffefffffe, // 109 + 0xfffffffffffffffe, // 110 + 0xffffffffffffffff, // 111 + 0xffffffffffffffff, // 112 + 0xfbfefef8fffefefb, // 113 + 0xfffffffcffffffff, // 114 + 0xfefefefdffffffff, // 115 + 0xffffffffffffffff, // 116 + 0xfffffffdffffffff, // 117 + 0xfffffffffdfdfdfb, // 118 + 0xffffffffffffffff, // 119 + 0xfffdfdffffffffff, // 120 + 0xffffffffffffffff, // 121 + 0xffffffffffffffff, // 122 + 0xfffffffffffffffd, // 123 + 0xfdfffefffffcfffe, // 124 + 0xfcfefffffffefeff, // 125 + 0xffffffffffffffff, // 126 + 0xffffffffffffffff, // 127 + 0xffffffffffffffff, // 128 + 0xfffbf8f8fbf8fefe, // 129 + 0xfffffffffefcfdff, // 130 + 0xfffffffffffffffd, // 131 + 0xffffffffffffffff, // 132 + 0xfffffffffcfcffff, // 133 + 0xffffffffffffffff, // 134 + 0xffffffffffffffff, // 135 + 0xfffffffffdfefdff, // 136 + 0xffffffffffffffff, // 137 + 0xfcfefbfdfffffffe, // 138 + 0xfffffffffeffffff, // 139 + 0xf8fbfefefefffeff, // 140 + 0xffffffffffffffff, // 141 + 0xfefefefffefffffe, // 142 + 0xffffffffffffffff, // 143 + 0xfffffffffcfefeff, // 144 + 0xffffffffffffffff, // 145 + 0xfffffffffffffffe, // 146 + 0xfffffffffffffffe, // 147 + 0xffffffffffffffff, // 148 + 0xfffffffffefffeff, // 149 + 0xfffefffeffffffff, // 150 + 0xffffffffffffffff, // 151 + 0xffffffffffffffff, // 152 + 0xfffffbfefffffcff, // 153 + 0xffffffffffffffff, // 154 + 0xfdfefefaffffffff, // 155 + 0xffffffffffffffff, // 156 + 0xfffffffffffffffd, // 157 + 0xfffffffffffffffe, // 158 + 0xffffffffffffffff, // 159 + 0xffffffffffffffff, // 160 + 0xfdfefefbfffbfffe, // 161 + 0xfffffffefffffffe, // 162 + 0xffffffffffffffff, // 163 + 0xffffffffffffffff, // 164 + 0xfeffffffffffffff, // 165 + 0xfffdfffdffffffff, // 166 + 0xfffffffdffffffff, // 167 + 0xfeffffffffffffff, // 168 + 0xffffffffffffffff, // 169 + 0xffffffffffffffff, // 170 + 0xffffffffffffffff, // 171 + 0xfcfffefefffefbfe, // 172 + 0xffffffffffffffff, // 173 + 0xfffffffffffeffff, // 174 + 0xffffffffffffffff, // 175 + 0xfffffffffffffffe, // 176 + 0xfffffffffdfefdfd, // 177 + 0xffffffffffffffff, // 178 + 0xffffffffffffffff, // 179 + 0xfffffffdffffffff, // 180 + 0xffffffffffffffff, // 181 + 0xffffffffffffffff, // 182 + 0xffffffffffffffff, // 183 + 0xffffffffffffffff, // 184 + 0xfbfffefffefefbfd, // 185 + 0xfffffffffffeffff, // 186 + 0xffffffffffffffff, // 187 + 0xffffffffffffffff, // 188 + 0xffffffffffffffff, // 189 + 0xffffffffffffffff, // 190 + 0xfffdfeffffffffff, // 191 + 0xffffffffffffffff, // 192 + 0xfffffffeffffffff, // 193 + 0xffffffffffffffff, // 194 + 0xffffffffffffffff, // 195 + 0xfffffffefeffffff, // 196 + 0xfcfefff8fefffbfe, // 197 + 0xffffffffffffffff, // 198 + 0xffffffffffffffff, // 199 + 0xffffffffffffffff, // 200 + 0xffffffffffffffff, // 201 + 0xffffffffffffffff, // 202 + 0xffffffffffffffff, // 203 + 0xffffffffffffffff, // 204 + 0xfbfbfefbfefefeff, // 205 + 0xffffffffffffffff, // 206 + 0xfffeffffffffffff, // 207 + 0xffffffffffffffff, // 208 + 0xffffffffffffffff, // 209 + 0xffffffffffffffff, // 210 + 0xffffffffffffffff, // 211 + 0xffffffffffffffff, // 212 + 0xfffffffffefeffff, // 213 + 0xfefefefeffffffff, // 214 + 0xffffffffffffffff, // 215 + 0xffffffffffffffff, // 216 + 0xfffffffffefeffff, // 217 + 0xfbfefbfefffefefb, // 218 + 0xffffffffffffffff, // 219 + 0xfffffffffffffffe, // 220 + 0xfffffffefdfffefe, // 221 + 0xffffffffffffffff, // 222 + 0xffffffffffffffff, // 223 + 0xffffffffffffffff, // 224 + 0xfffefffcffffffff, // 225 + 0xfffffefffffdfdff, // 226 + 0xfffefeffffffffff, // 227 + 0xfffffeffffffffff, // 228 + 0xffffffffffffffff, // 229 + 0xfffffffffefefefd, // 230 + 0xfcfdfefffefffffe, // 231 + 0xfefdffffffffffff, // 232 + 0xfffffffeffffffff, // 233 + 0xfdfefdffffffffff, // 234 + 0xffffffffffffffff, // 235 + 0xfdfefffeffffffff, // 236 + 0xffffffffffffffff, // 237 + 0xffffffffffffffff, // 238 + 0xfbfffffefbfefefe, // 239 + 0xfefcfdffffffffff, // 240 + 0xfffffffffffffffe, // 241 + 0xfffffffefefdfefd, // 242 + 0xffffffffffffffff, // 243 + 0xfffeffffffffffff, // 244 + 0xffffffffffffffff, // 245 + 0xfffffffeffffffff, // 246 + 0xffffffffffffffff, // 247 + 0xfffffffffefefeff, // 248 + 0xfffffffdfefffefe, // 249 + 0xfffefeffffffffff, // 250 + 0xffffffffffffffff, // 251 + 0xfbfbfefefefbfffe, // 252 + 0xffffffffffffffff, // 253 + 0xfffffffeffffffff, // 254 + 0xfffffffeffffffff, // 255 + 0xfefffeffffffffff, // 256 + 0xfffffdffffffffff, // 257 + 0xffffffffffffffff, // 258 + 0xffffffffffffffff, // 259 + 0xfffffffffdfffdff, // 260 + 0xfffffffffefffffe, // 261 + 0xfefffffffffffefe, // 262 + 0xfefffcfdfffefefb, // 263 + 0xffffffffffffffff, // 264 + 0xffffffffffffffff, // 265 + 0xffffffffffffffff, // 266 + 0xfffffffffeffffff, // 267 + 0xffffffffffffffff, // 268 + 0xffffffffffffffff, // 269 + 0xffffffffffffffff, // 270 + 0xfefbfefbfbfefefe, // 271 + 0xfffffffffffffdff, // 272 + 0xfffffffffffffffe, // 273 + 0xffffffffffffffff, // 274 + 0xffffffffffffffff, // 275 + 0xffffffffffffffff, // 276 + 0xffffffffffffffff, // 277 + 0xffffffffffffffff, // 278 + 0xffffffffffffffff, // 279 + 0xfffffcfcfffffeff, // 280 + 0xffffffffffffffff, // 281 + 0xfbf8fefefbfbfeff, // 282 + 0xfffffffffffffffe, // 283 + 0xfffffffffffffffe, // 284 + 0xffffffffffffffff, // 285 + 0xffffffffffffffff, // 286 + 0xffffffffffffffff, // 287 + 0xffffffffffffffff, // 288 + 0xffffffffffffffff, // 289 + 0xffffffffffffffff, // 290 + 0xffffffffffffffff, // 291 + 0xffffffffffffffff, // 292 + 0xffffffffffffffff, // 293 + 0xffffffffffffffff, // 294 + 0xffffffffffffffff, // 295 + 0xfefefdfcfdfefffe, // 296 + 0xfffffffeffffffff, // 297 + 0xffffffffffffffff, // 298 + 0xfffffeffffffffff, // 299 + 0xffffffffffffffff, // 300 + 0xfffefffffefefffe, // 301 + 0xfffffffeffffffff, // 302 + 0xffffffffffffffff, // 303 + 0xfbfffefefbfefffe, // 304 + 0xffffffffffffffff, // 305 + 0xfffffffffffeffff, // 306 + 0xffffffffffffffff, // 307 + 0xfffeffffffffffff, // 308 + 0xffffffffffffffff, // 309 + 0xffffffffffffffff, // 310 + 0xffffffffffffffff, // 311 + 0xffffffffffffffff, // 312 + 0xffffffffffffffff, // 313 + 0xffffffffffffffff, // 314 + 0xffffffffffffffff, // 315 + 0xfffffffeffffffff, // 316 + 0xfbfefbfbfefbfeff, // 317 + 0xffffffffffffffff, // 318 + 0xfffffffefefeffff, // 319 + 0xfffffffeffffffff, // 320 + 0xffffffffffffffff, // 321 + 0xffffffffffffffff, // 322 + 0xffffffffffffffff, // 323 + 0xffffffffffffffff, // 324 + 0xffffffffffffffff, // 325 + 0xffffffffffffffff, // 326 + 0xffffffffffffffff, // 327 + 0xffffffffffffffff, // 328 + 0xfffffffffefefeff, // 329 + 0xfefefefefbfdfeff, // 330 + 0xffffffffffffffff, // 331 + 0xffffffffffffffff, // 332 + 0xfffffffffeffffff, // 333 + 0xffffffffffffffff, // 334 + 0xfefffffffffffffe, // 335 + 0xfcfbfefffefbfefe, // 336 + 0xfffffffffffefeff, // 337 + 0xffffffffffffffff, // 338 + 0xffffffffffffffff, // 339 + 0xfeffffffffffffff, // 340 + 0xfffdfeffffffffff, // 341 + 0xffffffffffffffff, // 342 + 0xffffffffffffffff, // 343 + 0xffffffffffffffff, // 344 + 0xffffffffffffffff, // 345 + 0xfffffffdffffffff, // 346 + 0xffffffffffffffff, // 347 + 0xfefbfbfefbfeffff, // 348 + 0xffffffffffffffff, // 349 + 0xffffffffffffffff, // 350 + 0xffffffffffffffff, // 351 + 0xffffffffffffffff, // 352 + 0xffffffffffffffff, // 353 + 0xffffffffffffffff, // 354 + 0xffffffffffffffff, // 355 + 0xfffffffeffffffff, // 356 + 0xffffffffffffffff, // 357 + 0xffffffffffffffff, // 358 + 0xfefbfefffefffbff, // 359 + 0xffffffffffffffff, // 360 + 0xfefffffffffffffe, // 361 + 0xffffffffffffffff, // 362 + 0xffffffffffffffff, // 363 + 0xffffffffffffffff, // 364 + 0xfffffefdffffffff, // 365 + 0xfffffffeffffffff, // 366 + 0xffffffffffffffff, // 367 + 0xfffefefefffffffe, // 368 + 0xfffffffffffffffe, // 369 + 0xfffffffffffffffc, // 370 + 0xfcfdfffefefbfffe, // 371 + 0xfcfdfcfcfffffffe, // 372 + 0xffffffffffffffff, // 373 + 0xffffffffffffffff, // 374 + 0xffffffffffffffff, // 375 + 0xfdfdfffeffffffff, // 376 + 0xfffffffffffffeff, // 377 + 0xfffffffeffffffff, // 378 + 0xfbfefefbfbfefefb, // 379 + 0xfffffffdffffffff, // 380 + 0xffffffffffffffff, // 381 + 0xffffffffffffffff, // 382 + 0xffffffffffffffff, // 383 + 0xffffffffffffffff, // 384 + 0xffffffffffffffff, // 385 + 0xffffffffffffffff, // 386 + 0xfffffffffffffffe, // 387 + 0xfffffffffffffffe, // 388 + 0xffffffffffffffff, // 389 + 0xffffffffffffffff, // 390 + 0xffffffffffffffff, // 391 + 0xfefefbfbfefffeff, // 392 + 0xfffffffffffffffe, // 393 + 0xffffffffffffffff, // 394 + 0xfffffffffffffffd, // 395 + 0xffffffffffffffff, // 396 + 0xffffffffffffffff, // 397 + 0xffffffffffffffff, // 398 + 0xfffeffffffffffff, // 399 + 0xffffffffffffffff, // 400 + 0xffffffffffffffff, // 401 + 0xfffffefeffffffff, // 402 + 0xfefdfcfefffffeff, // 403 + 0xffffffffffffffff, // 404 + 0xfffffffffffffffe, // 405 + 0xffffffffffffffff, // 406 + 0xffffffffffffffff, // 407 + 0xfffffffeffffffff, // 408 + 0xffffffffffffffff, // 409 + 0xfffffffffefeffff, // 410 + 0xfefefbfbfefbfefe, // 411 + 0xfffffffffffefffe, // 412 + 0xffffffffffffffff, // 413 + 0xffffffffffffffff, // 414 + 0xfffffffffffffffe, // 415 + 0xffffffffffffffff, // 416 + 0xffffffffffffffff, // 417 + 0xfffffffffffffffe, // 418 + 0xfffffffffffffffe, // 419 + 0xfffffffffffffffe, // 420 + 0xffffffffffffffff, // 421 + 0xfffffffefffeffff, // 422 + 0xfffffffeffffffff, // 423 + 0xfffffffeffffffff, // 424 + 0xfefefefefefbfbfe, // 425 + 0xfffffffffdfffefb, // 426 + 0xfffffffeffffffff, // 427 + 0xfffffffeffffffff, // 428 + 0xfffdfdfffffffffe, // 429 + 0xfef8fffbfefbfeff, // 430 + 0xffffffffffffffff, // 431 + 0xffffffffffffffff, // 432 + 0xfffffffffffefdfe, // 433 + 0xffffffffffffffff, // 434 + 0xffffffffffffffff, // 435 + 0xffffffffffffffff, // 436 + 0xffffffffffffffff, // 437 + 0xfefffeffffffffff, // 438 + 0xfcfdfefbfffefefb, // 439 + 0xffffffffffffffff, // 440 + 0xffffffffffffffff, // 441 + 0xffffffffffffffff, // 442 + 0xffffffffffffffff, // 443 + 0xfffefeffffffffff, // 444 + 0xffffffffffffffff, // 445 + 0xffffffffffffffff, // 446 + 0xfffffffeffffffff, // 447 + 0xffffffffffffffff, // 448 + 0xffffffffffffffff, // 449 + 0xfefbfbfefffffffe, // 450 + 0xffffffffffffffff, // 451 + 0xfffffffffeffffff, // 452 + 0xffffffffffffffff, // 453 + 0xffffffffffffffff, // 454 + 0xfffffffeffffffff, // 455 + 0xffffffffffffffff, // 456 + 0xffffffffffffffff, // 457 + 0xffffffffffffffff, // 458 + 0xffffffffffffffff, // 459 + 0xfffffffefffffffe, // 460 + 0xfbfefefbfffbfbfe, // 461 + 0xfffffffffffffffe, // 462 + 0xffffffffffffffff, // 463 + 0xfefdfeffffffffff, // 464 + 0xffffffffffffffff, // 465 + 0xffffffffffffffff, // 466 + 0xffffffffffffffff, // 467 + 0xfefffefeffffffff, // 468 + 0xfffffffffeffffff, // 469 + 0xffffffffffffffff, // 470 + 0xfffffffdffffffff, // 471 + 0xffffffffffffffff, // 472 + 0xfffffffffdfbfbfe, // 473 + 0xfcfdfefffefbfffe, // 474 + 0xfffffffffffdfffe, // 475 + 0xfffffffffefdffff, // 476 + 0xffffffffffffffff, // 477 + 0xfefffffeffffffff, // 478 + 0xfdfffefdfefffefd, // 479 + 0xffffffffffffffff, // 480 + 0xfffbfefbfefbfefb, // 481 + 0xfbfcfdfdffffffff, // 482 + 0xfffffffffffffffe, // 483 + 0xfffffffffffffffe, // 484 + 0xffffffffffffffff, // 485 + 0xfffffffffffffffe, // 486 + 0xfffffefffffffffe, // 487 + 0xffffffffffffffff, // 488 + 0xffffffffffffffff, // 489 + 0xffffffffffffffff, // 490 + 0xffffffffffffffff, // 491 + 0xffffffffffffffff, // 492 + 0xffffffffffffffff, // 493 + 0xffffffffffffffff, // 494 + 0xfbfefefbfffef8fe, // 495 + 0xffffffffffffffff, // 496 + 0xffffffffffffffff, // 497 + 0xffffffffffffffff, // 498 + 0xffffffffffffffff, // 499 + 0xfffffffeffffffff, // 500 + 0xffffffffffffffff, // 501 + 0xfffffffffffffffe, // 502 + 0xffffffffffffffff, // 503 + 0xfffffffffffffffe, // 504 + 0xffffffffffffffff, // 505 + 0xfffffffffffffffe, // 506 + 0xfcfdfffffefefbff, // 507 + 0xffffffffffffffff, // 508 + 0xffffffffffffffff, // 509 + 0xffffffffffffffff, // 510 + 0xffffffffffffffff, // 511 + 0xffffffffffffffff, // 512 + 0xfefbfefefefefbfe, // 513 + 0xffffffffffffffff, // 514 + 0xfffffeffffffffff, // 515 + 0xffffffffffffffff, // 516 + 0xfffffffeffffffff, // 517 + 0xfffffffeffffffff, // 518 + 0xfffffffeffffffff, // 519 + 0xfffffffefefeffff, // 520 + 0xffffffffffffffff, // 521 + 0xfefbfbfefbfefefb, // 522 + 0xffffffffffffffff, // 523 + 0xffffffffffffffff, // 524 + 0xffffffffffffffff, // 525 + 0xffffffffffffffff, // 526 + 0xffffffffffffffff, // 527 + 0xffffffffffffffff, // 528 + 0xffffffffffffffff, // 529 + 0xffffffffffffffff, // 530 + 0xffffffffffffffff, // 531 + 0xffffffffffffffff, // 532 + 0xffffffffffffffff, // 533 + 0xfffefefbfcfdfeff, // 534 + 0xffffffffffffffff, // 535 + 0xffffffffffffffff, // 536 + 0xffffffffffffffff, // 537 + 0xffffffffffffffff, // 538 + 0xffffffffffffffff, // 539 + 0xffffffffffffffff, // 540 + 0xffffffffffffffff, // 541 + 0xffffffffffffffff, // 542 + 0xfbfbfefffefefbfb, // 543 + 0xffffffffffffffff, // 544 + 0xffffffffffffffff, // 545 + 0xffffffffffffffff, // 546 + 0xffffffffffffffff, // 547 + 0xffffffffffffffff, // 548 + 0xffffffffffffffff, // 549 + 0xffffffffffffffff, // 550 + 0xffffffffffffffff, // 551 + 0xffffffffffffffff, // 552 + 0xfefefbffffffffff, // 553 + 0xffffffffffffffff, // 554 + 0xffffffffffffffff, // 555 + 0xffffffffffffffff, // 556 + 0xffffffffffffffff, // 557 + ]; + + // Do a test run against the interpreter, then check the compiler. + for hash_type in [ + HashXType::HASHX_TYPE_INTERPRETED, + HashXType::HASHX_TYPE_COMPILED, + ] { + let mut ctx = HashX::new(hash_type); + + // Fully replace the Rng stream, which must be exactly the right size + let counter = Arc::new(RefCell::new(0_usize)); + { + let counter = counter.clone(); + ctx.rng_callback(Some(Box::new(move |_value| { + let mut counter = counter.borrow_mut(); + let result = SEQUENCE[*counter]; + *counter += 1; + result + }))); + } + + // Seed choice: This seed will normally fail constraint checks. + // Using it here is a way of verifying that Rng replacement works. + assert_eq!(*counter.borrow(), 0); + assert_eq!(ctx.make(b"qfjsfv"), HashXResult::HASHX_OK); + assert_eq!(*counter.borrow(), SEQUENCE.len()); + assert_eq!(ctx.query_type(), Ok(hash_type)); + + // Make sure we can run the hash function, spot-testing the output. + assert_eq!(ctx.exec(0).unwrap(), hex!("7d7442b95fc9ea3d")); + assert_eq!(ctx.exec(123).unwrap(), hex!("1519ee923bf1e699")); + assert_eq!(ctx.exec(12345).unwrap(), hex!("726c4073ff1bb595")); + } + } }