hashx: Fix rare compiler output overflow on aarch64

This is a fix for a very rare buffer overflow in hashx, specific to the
dynamic compiler on aarch64 platforms.

In practice this issue is extremely unlikely to hit randomly, and it's
only been seen in unit tests that supply unusual mock PRNG output to the
program generator. My best attempt at estimating the probability of
hitting the overflow randomly is about 10^-23. Crafting an input with
the intent to overflow can be done only as fast as an exhaustive search,
so long as Blake2B is unbroken.

The root cause is that hashx writes assembly code without any length
checks, and it uses an estimated size rather than an absolute maximum
size to allocate the buffer for compiled code. Some instructions are
much longer than others, especially on aarch64.

The length of the overflow is nearly 300 bytes in the worst synthetic
test cases I've developed so far. Overflow occurs during hashx_make(),
and the subsequent hashx_exec() will always SIGSEGV as the written code
crosses outside the region that's been marked executable. In typical use,
hashx_exec() is called immediately after hashx_make().

This fix increases the buffer size from 1 page to 2 pages on aarch64,
adds an analysis of the compiled code size, and adds runtime checks so we
can gracefully fail on overflow. It also adds a unit test (written in
Rust) that includes a PRNG sequence exercising the overflow. Without
this patch the unit test shows a SIGSEGV on aarch64, with this patch it
runs successfully and matches interpreter output.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
This commit is contained in:
Micah Elizabeth Scott 2023-08-11 14:34:05 -07:00
parent 3d63d713ea
commit a94ce25277
4 changed files with 678 additions and 7 deletions

View file

@ -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

View file

@ -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 (int 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;

View file

@ -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);
}

View file

@ -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"));
}
}
}