Skip to content

Commit 75bd6c7

Browse files
Add reply type_id/opcode identity validation to all _get_* wrappers
1 parent 033f9f4 commit 75bd6c7

6 files changed

Lines changed: 30 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ All notable changes to CRUMBS are documented in this file.
3939
- Eight-step walkthrough using a toy thermometer peripheral as a running example
4040
- Covers: type ID selection, ops header structure, SET/SET*REPLY op pairs, result structs, `\_get*\*` pattern, Linux and Arduino usage, helper reference tables, and a completeness checklist
4141

42+
### Fixed
43+
44+
- **Reply identity validation in all `_get_*` wrappers**
45+
- All 11 `_get_*` functions (across `led_ops.h`, `servo_ops.h`, `calculator_ops.h`, `display_ops.h`, `mock_ops.h`) now verify that `reply.type_id` and `reply.opcode` match the expected values before parsing
46+
- Returns `-1` immediately on any mismatch, preventing silent data corruption when a valid CRUMBS frame arrives from the wrong device type or address
47+
- For `calc_get_hist_entry`, the identity check precedes the `data_len < 16` check
48+
- Zero runtime cost on the happy path; two comparisons per GET on any error path
49+
4250
### Changed
4351

4452
- **Example controllers updated to use `_get_*` wrappers** (`examples/families_usage/`)

examples/families_usage/lhwit_family/calculator_ops.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,8 @@ extern "C"
364364
rc = crumbs_controller_read(ctx, addr, &reply, read_fn, io);
365365
if (rc != 0)
366366
return rc;
367+
if (reply.type_id != CALC_TYPE_ID || reply.opcode != CALC_OP_GET_RESULT)
368+
return -1;
367369
return crumbs_msg_read_u32(reply.data, reply.data_len, 0, &out->result);
368370
}
369371

@@ -398,6 +400,8 @@ extern "C"
398400
rc = crumbs_controller_read(ctx, addr, &reply, read_fn, io);
399401
if (rc != 0)
400402
return rc;
403+
if (reply.type_id != CALC_TYPE_ID || reply.opcode != CALC_OP_GET_HIST_META)
404+
return -1;
401405
rc = crumbs_msg_read_u8(reply.data, reply.data_len, 0, &out->count);
402406
if (rc != 0)
403407
return rc;
@@ -440,6 +444,8 @@ extern "C"
440444
rc = crumbs_controller_read(ctx, addr, &reply, read_fn, io);
441445
if (rc != 0)
442446
return rc;
447+
if (reply.type_id != CALC_TYPE_ID || reply.opcode != (uint8_t)(CALC_OP_GET_HIST_0 + entry_idx))
448+
return -1;
443449
if (reply.data_len < 16)
444450
return -1; /* Entry is empty or malformed */
445451
/* Parse: [op:4][a:u32][b:u32][result:u32] */

examples/families_usage/lhwit_family/display_ops.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ extern "C"
294294
rc = crumbs_controller_read(ctx, addr, &reply, read_fn, io);
295295
if (rc != 0)
296296
return rc;
297+
if (reply.type_id != DISPLAY_TYPE_ID || reply.opcode != DISPLAY_OP_GET_VALUE)
298+
return -1;
297299
/* Reply: [number:u16][decimal_pos:u8][brightness:u8] */
298300
return display_parse_get_value(reply.data, reply.data_len,
299301
&out->number, &out->decimal_pos, &out->brightness);

examples/families_usage/lhwit_family/led_ops.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,8 @@ extern "C"
270270
rc = crumbs_controller_read(ctx, addr, &reply, read_fn, io);
271271
if (rc != 0)
272272
return rc;
273+
if (reply.type_id != LED_TYPE_ID || reply.opcode != LED_OP_GET_STATE)
274+
return -1;
273275
return crumbs_msg_read_u8(reply.data, reply.data_len, 0, &out->states);
274276
}
275277

@@ -304,6 +306,8 @@ extern "C"
304306
rc = crumbs_controller_read(ctx, addr, &reply, read_fn, io);
305307
if (rc != 0)
306308
return rc;
309+
if (reply.type_id != LED_TYPE_ID || reply.opcode != LED_OP_GET_BLINK)
310+
return -1;
307311
/* Reply: [led0_enable:u8][led0_period:u16]...[led3_enable:u8][led3_period:u16] */
308312
for (uint8_t i = 0; i < 4; i++)
309313
{

examples/families_usage/lhwit_family/servo_ops.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,8 @@ extern "C"
277277
rc = crumbs_controller_read(ctx, addr, &reply, read_fn, io);
278278
if (rc != 0)
279279
return rc;
280+
if (reply.type_id != SERVO_TYPE_ID || reply.opcode != SERVO_OP_GET_POS)
281+
return -1;
280282
rc = crumbs_msg_read_u8(reply.data, reply.data_len, 0, &out->pos[0]);
281283
if (rc != 0)
282284
return rc;
@@ -314,6 +316,8 @@ extern "C"
314316
rc = crumbs_controller_read(ctx, addr, &reply, read_fn, io);
315317
if (rc != 0)
316318
return rc;
319+
if (reply.type_id != SERVO_TYPE_ID || reply.opcode != SERVO_OP_GET_SPEED)
320+
return -1;
317321
rc = crumbs_msg_read_u8(reply.data, reply.data_len, 0, &out->speed[0]);
318322
if (rc != 0)
319323
return rc;

examples/handlers_usage/mock_ops.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,8 @@ extern "C"
284284
rc = crumbs_controller_read(ctx, addr, &reply, read_fn, io);
285285
if (rc != 0)
286286
return rc;
287+
if (reply.type_id != MOCK_TYPE_ID || reply.opcode != MOCK_OP_GET_ECHO)
288+
return -1;
287289
out->len = reply.data_len;
288290
if (reply.data_len > 0)
289291
memcpy(out->data, reply.data, reply.data_len);
@@ -321,6 +323,8 @@ extern "C"
321323
rc = crumbs_controller_read(ctx, addr, &reply, read_fn, io);
322324
if (rc != 0)
323325
return rc;
326+
if (reply.type_id != MOCK_TYPE_ID || reply.opcode != MOCK_OP_GET_STATUS)
327+
return -1;
324328
rc = crumbs_msg_read_u8(reply.data, reply.data_len, 0, &out->state);
325329
if (rc != 0)
326330
return rc;
@@ -358,6 +362,8 @@ extern "C"
358362
rc = crumbs_controller_read(ctx, addr, &reply, read_fn, io);
359363
if (rc != 0)
360364
return rc;
365+
if (reply.type_id != MOCK_TYPE_ID || reply.opcode != MOCK_OP_GET_INFO)
366+
return -1;
361367
out->len = reply.data_len;
362368
if (reply.data_len > 0)
363369
memcpy(out->info, reply.data, reply.data_len);

0 commit comments

Comments
 (0)