Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
fuzz_harness.h
Go to the documentation of this file.
1#pragma once
23#include <stddef.h>
24#include <stdint.h>
25#include <string.h>
26#include <setjmp.h>
27#include "fuzz_defs.h"
28/* Optional: an app includes its own mocks.h only if it genuinely has
29 * app-specific stubs. The framework symbols this harness needs are declared
30 * in fuzz_defs.h. */
31#if __has_include("mocks.h")
32#include "mocks.h"
33#endif
34#include "parser.h"
35
37extern const size_t fuzz_n_commands;
38extern void fuzz_app_reset(void);
39extern void fuzz_app_dispatch(void *cmd);
40
45extern void fuzz_app_cleanup(void);
46
49
51static inline int fuzz_use_structured_lane(void)
52{
54}
55
57static inline uint8_t fuzz_clamp_p(uint8_t raw, uint8_t p_max)
58{
59 if (p_max == 0) {
60 return raw;
61 }
62 return raw % (p_max + 1);
63}
64
71#ifndef FUZZ_APP_HEADER_LEN
72#define FUZZ_APP_HEADER_LEN 0
73#endif
74
76#ifndef FUZZ_PICK_COMMAND_STRUCTURED
77#define FUZZ_PICK_COMMAND_STRUCTURED(data, size) (&fuzz_commands[(data)[1] % fuzz_n_commands])
78#endif
79
80#ifndef FUZZ_PICK_COMMAND_RAW
81#define FUZZ_PICK_COMMAND_RAW(data, size) (&fuzz_commands[(data)[1] % fuzz_n_commands])
82#endif
83
84static void fuzz_harness_cleanup(void)
85{
87 fuzz_tail_ptr = NULL;
88 fuzz_tail_len = 0;
89 try_context_set(NULL);
90 memset(&fuzz_exit_jump_ctx, 0, sizeof(fuzz_exit_jump_ctx));
91}
92
100static int fuzz_harness_entry(const uint8_t *data, size_t size)
101{
102 try_context_set(&fuzz_exit_jump_ctx);
103
104 if (sigsetjmp(fuzz_exit_jump_ctx.jmp_buf, 1)) {
106 return 0;
107 }
108
109 const size_t header = (size_t) FUZZ_CTRL_LEN + FUZZ_APP_HEADER_LEN;
110
111 if (size < header || fuzz_n_commands == 0) {
112 return -1;
113 }
114
116
117 /* Published before fuzz_app_reset() so an app can read its own input while
118 * establishing state. */
119 fuzz_tail_ptr = (size > header) ? data + header : NULL;
120 fuzz_tail_len = (size > header) ? size - header : 0;
121
123
124 const fuzz_command_spec_t *spec;
126 spec = FUZZ_PICK_COMMAND_STRUCTURED(data, size);
127 }
128 else {
129 spec = FUZZ_PICK_COMMAND_RAW(data, size);
130 }
131
132 command_t cmd;
133 memset(&cmd, 0, sizeof(cmd));
134
135 cmd.cla = spec->cla;
136 cmd.ins = spec->ins;
137 cmd.p1 = fuzz_clamp_p(data[2], spec->p1_max);
138 cmd.p2 = fuzz_clamp_p(data[3], spec->p2_max);
139
140 if (fuzz_tail_len > 0) {
141 cmd.lc = (uint8_t) (fuzz_tail_len > 255 ? 255 : fuzz_tail_len);
142 cmd.data = (uint8_t *) fuzz_tail_ptr;
143 }
144
145 fuzz_app_dispatch(&cmd);
147 return 0;
148}
149
158#include "fuzz_mutator.h"
159
160#ifndef FUZZ_APP_CUSTOM_MUTATOR
161size_t LLVMFuzzerCustomMutator(uint8_t *data, size_t size, size_t max_size, unsigned int seed)
162{
163 return fuzz_custom_mutator(data, size, max_size, seed);
164}
165#endif
166
174#ifndef FUZZ_APP_CUSTOM_ENTRY
175int fuzz_entry(const uint8_t *data, size_t size);
176int fuzz_entry(const uint8_t *data, size_t size)
177{
178 return fuzz_harness_entry(data, size);
179}
180#endif
Shared constants, the input layout, and the command descriptor type for SDK fuzz harnesses.
#define FUZZ_STRUCTURED_LANE_THRESHOLD
Control byte 0 above this value selects the structured lane; at or below it the harness takes the raw...
Definition fuzz_defs.h:89
size_t fuzz_tail_len
Length of fuzz_tail_ptr in bytes.
#define FUZZ_CTRL_LEN
Bytes 0..3 steer the harness; byte 4 onwards is payload.
Definition fuzz_defs.h:73
const uint8_t * fuzz_tail_ptr
The APDU payload for the current iteration (NULL when empty).
try_context_t fuzz_exit_jump_ctx
longjmp landing pad the harness unwinds os_exit() through.
static int fuzz_harness_entry(const uint8_t *data, size_t size)
Default fuzz_entry() body: run one fuzzer input as one APDU.
int fuzz_entry(const uint8_t *data, size_t size)
Default fuzz_entry(), the symbol Absolution calls per iteration.
static int fuzz_lane_structured
#define FUZZ_APP_HEADER_LEN
Bytes an app reserves for its own header, right after the control bytes.
void fuzz_app_reset(void)
Reset app state before each iteration (optional).
void fuzz_app_cleanup(void)
Optional per-iteration teardown; the weak no-op default is in mock/fuzz_runtime.c.
#define FUZZ_PICK_COMMAND_RAW(data, size)
void fuzz_app_dispatch(void *cmd)
Dispatch one command_t to the app (required).
const size_t fuzz_n_commands
Number of entries in fuzz_commands.
size_t LLVMFuzzerCustomMutator(uint8_t *data, size_t size, size_t max_size, unsigned int seed)
Default custom mutator.
static uint8_t fuzz_clamp_p(uint8_t raw, uint8_t p_max)
Clamp a raw P1/P2 byte to the command's declared maximum (0 = full range).
const fuzz_command_spec_t fuzz_commands[]
App command table.
static int fuzz_use_structured_lane(void)
Whether control byte 0 selected the structured lane.
#define FUZZ_PICK_COMMAND_STRUCTURED(data, size)
static void fuzz_harness_cleanup(void)
Prefix-aware LibFuzzer custom mutator.
size_t fuzz_custom_mutator(uint8_t *data, size_t size, size_t max_size, unsigned int seed)
The framework's LLVMFuzzerCustomMutator() body.
uint8_t ins
Instruction class.
Definition parser.h:12
uint8_t lc
Instruction parameter 2.
Definition parser.h:15
uint8_t cla
Definition parser.h:11
uint8_t p1
Instruction code.
Definition parser.h:13
uint8_t p2
Instruction parameter 1.
Definition parser.h:14
uint8_t * data
Length of command data.
Definition parser.h:16
Describes one APDU command the harness may synthesise and dispatch.
Definition fuzz_defs.h:95
uint8_t p2_max
Upper bound for P2 (0 = full range [0,255]).
Definition fuzz_defs.h:99
uint8_t p1_max
Upper bound for P1 (0 = full range [0,255]).
Definition fuzz_defs.h:98
uint8_t ins
APDU instruction byte.
Definition fuzz_defs.h:97
uint8_t cla
APDU class byte.
Definition fuzz_defs.h:96