MaJerle / lwgps

Lightweight GPS NMEA parser for embedded systems
MIT License
389 stars 128 forks source link

Undefined Behavior in prv_parse_lat_long() and prv_parse_number() #25

Closed invd closed 9 months ago

invd commented 1 year ago

prv_parse_lat_long()

lwgps.c:142:11: runtime error: 3.33333e+09 is outside the range of representable values of type 'int'

Code location: https://github.com/MaJerle/lwgps/blob/c094d2afcd86b71ed042d654cad26d4b3b18e26c/lwgps/src/lwgps/lwgps.c#L142

Hexdump of problematic input:

00000000  24 47 4e 47 47 41 2c 2c  33 33 33 33 33 33 33 33  |$GNGGA,,33333333|
00000010  37 32 2c                                          |72,|

prv_parse_number()

lwgps.c:90:18: runtime error: signed integer overflow: 10 * 666666666 cannot be represented in type 'int'

Code location: https://github.com/MaJerle/lwgps/blob/c094d2afcd86b71ed042d654cad26d4b3b18e26c/lwgps/src/lwgps/lwgps.c#L90

Hexdump of problematic input:

00000000  24 47 4e 47 53 41 2c 2c  36 36 2c 36 36 36 36 36  |$GNGSA,,66,66666|
00000010  36 36 36 36 36 32 37 2a                           |6666627*|

libFuzzer harness in use

Derived from example.c and published under same license.

#include "lwgps.h"

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {

  lwgps_t hgps;
  lwgps_init(&hgps);

  /* Process all input data */
  lwgps_process(&hgps, data, size);

  return 0;
}
MaJerle commented 1 year ago

Why is the input value so large?

invd commented 1 year ago

I found the mentioned edge cases during fuzzing with libFuzzer in combination with UBSan. As such, they don't represent output seen from interacting with actual GPS hardware modules.

To make lwgps robust against problematic behavior when encountering such input, I recommend handling or rejecting large values in the calculations more deliberately to avoid running into undefined behavior.