Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
tlv_mutator.h
Go to the documentation of this file.
1#pragma once
11#include <stddef.h>
12#include <stdint.h>
13
15typedef struct {
16 uint8_t tag;
17 uint8_t min_len;
18 uint8_t max_len;
20
22typedef struct {
24 size_t num_tags;
26
29
31#define TLV_CFG(arr) \
32 { \
33 .tags_info = (arr), .num_tags = sizeof(arr) / sizeof((arr)[0]) \
34 }
35
37size_t tlv_custom_mutate(uint8_t *data, size_t size, size_t max_size, unsigned int seed);
38
39/*
40 * Indexed-grammar dispatch helper: picks the active command's grammar from
41 * configs[] and mutates that command's TLV payload, falling back to the generic
42 * mutator otherwise.
43 *
44 * The command index is read from the harness input's control bytes (see
45 * fuzz_defs.h), the same bytes fuzz_harness_entry() uses to select the command,
46 * so the grammar chosen here always matches the command that will run.
47 */
48#include "fuzz_mutator.h"
49
50extern const size_t fuzz_n_commands;
51
52static inline size_t fuzz_tlv_dispatch_mutate(uint8_t *data,
53 size_t size,
54 size_t max_size,
55 unsigned int seed,
56 const tlv_fuzz_config_t *configs,
57 size_t n_configs)
58{
59 const size_t ps = fuzz_prefix_size();
60
61 /* Need the prefix plus control bytes plus a 2-byte payload length header. */
62 if (ps == 0 || ps + FUZZ_CTRL_LEN + 2 >= max_size || size <= ps + FUZZ_CTRL_LEN + 2) {
63 return fuzz_custom_mutator(data, size, max_size, seed);
64 }
65
66 uint8_t *input = data + ps;
67 size_t cmd_idx = input[1] % fuzz_n_commands;
68
69 if (cmd_idx >= n_configs || configs[cmd_idx].num_tags == 0 || (seed & 1U) != 0) {
70 return fuzz_custom_mutator(data, size, max_size, seed);
71 }
72
73 current_tlv_fuzz_config = configs[cmd_idx];
74
75 uint8_t *payload = input + FUZZ_CTRL_LEN;
76 size_t payload_size = size - ps - FUZZ_CTRL_LEN;
77 size_t max_payload = max_size - ps - FUZZ_CTRL_LEN;
78
79 /* First two payload bytes carry the TLV length. */
80 size_t tlv_size = tlv_custom_mutate(payload + 2, payload_size - 2, max_payload - 2, seed >> 2);
81
82 payload[0] = (uint8_t) (tlv_size >> 8);
83 payload[1] = (uint8_t) (tlv_size & 0xFF);
84
85 return ps + FUZZ_CTRL_LEN + 2 + tlv_size;
86}
#define FUZZ_CTRL_LEN
Bytes 0..3 steer the harness; byte 4 onwards is payload.
Definition fuzz_defs.h:73
Prefix-aware LibFuzzer custom mutator.
size_t fuzz_prefix_size(void)
Where Absolution's sampled state ends (see cmake/EmitPrefixSize.cmake).
size_t fuzz_custom_mutator(uint8_t *data, size_t size, size_t max_size, unsigned int seed)
The framework's LLVMFuzzerCustomMutator() body.
The TLV grammar the mutator currently applies (one per command).
Definition tlv_mutator.h:22
size_t num_tags
Number of entries in tags_info.
Definition tlv_mutator.h:24
const tlv_tag_info_t * tags_info
Array of allowed tags.
Definition tlv_mutator.h:23
Length bounds the mutator keeps for one TLV tag.
Definition tlv_mutator.h:15
uint8_t min_len
Minimum value length to emit.
Definition tlv_mutator.h:17
uint8_t tag
TLV tag byte.
Definition tlv_mutator.h:16
uint8_t max_len
Maximum value length to emit.
Definition tlv_mutator.h:18
tlv_fuzz_config_t current_tlv_fuzz_config
const size_t fuzz_n_commands
static size_t fuzz_tlv_dispatch_mutate(uint8_t *data, size_t size, size_t max_size, unsigned int seed, const tlv_fuzz_config_t *configs, size_t n_configs)
Definition tlv_mutator.h:52
size_t tlv_custom_mutate(uint8_t *data, size_t size, size_t max_size, unsigned int seed)
Mutate a TLV byte range in place, preserving valid framing.