Skip to content

Commit 775e962

Browse files
fix: add strict format validation to coordinate parsing
Addresses Copilot review comments - parsing functions now reject trailing garbage characters: - RA: '12:34:56XYZ' now rejected (only '12:34:56' accepted) - DEC: '+45*30:15XYZ' now rejected - Latitude: '+45*30X' now rejected - Longitude: '123*45abc' now rejected - Date: '03/15/23XYZ' now rejected - Time: '12:34:56xyz' now rejected All coordinate/date/time substrings are now validated to be exactly the expected length before numeric parsing. Fixes discussion r2404181093 and related validation issues. All 240 tests passing.
1 parent 8b852f1 commit 775e962

1 file changed

Lines changed: 34 additions & 5 deletions

File tree

lib/lx200/src/coordinates.cpp

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,12 @@ ParseResult parse_ra_coordinate(
8787
return ParseResult::ErrorOutOfRange;
8888
}
8989

90-
// Parse seconds (must be exactly 2 digits)
90+
// Parse seconds (must be exactly 2 digits, no trailing characters)
9191
std::string_view second_part = minute_part.substr(colon2_pos + 1);
92+
if (second_part.size() != 2) {
93+
return ParseResult::ErrorInvalidFormat;
94+
}
95+
9296
uint32_t seconds;
9397
if (!parse_uint(second_part.data(), 2, seconds)) {
9498
return ParseResult::ErrorInvalidFormat;
@@ -118,8 +122,12 @@ ParseResult parse_ra_coordinate(
118122
return ParseResult::ErrorOutOfRange;
119123
}
120124

121-
// Parse tenths (0-9)
125+
// Parse tenths (must be exactly 1 digit, no trailing characters)
122126
std::string_view tenth_part = minute_part.substr(dot_pos + 1);
127+
if (tenth_part.size() != 1) {
128+
return ParseResult::ErrorInvalidFormat;
129+
}
130+
123131
uint32_t tenths;
124132
if (!parse_uint(tenth_part.data(), 1, tenths)) {
125133
return ParseResult::ErrorInvalidFormat;
@@ -192,8 +200,12 @@ ParseResult parse_dec_coordinate(
192200
return ParseResult::ErrorOutOfRange;
193201
}
194202

195-
// Parse arcseconds
203+
// Parse arcseconds (must be exactly 2 digits, no trailing characters)
196204
std::string_view arcsec_part = arcmin_part.substr(sep_pos + 1);
205+
if (arcsec_part.size() != 2) {
206+
return ParseResult::ErrorInvalidFormat;
207+
}
208+
197209
uint32_t arcseconds;
198210
if (!parse_uint(arcsec_part.data(), 2, arcseconds)) {
199211
return ParseResult::ErrorInvalidFormat;
@@ -218,7 +230,11 @@ ParseResult parse_dec_coordinate(
218230
}
219231
}
220232
else {
221-
// Low precision: sDD*MM
233+
// Low precision: sDD*MM (must be exactly 2 digits, no trailing characters)
234+
if (arcmin_part.size() != 2) {
235+
return ParseResult::ErrorInvalidFormat;
236+
}
237+
222238
uint32_t arcminutes;
223239
if (!parse_uint(arcmin_part.data(), 2, arcminutes)) {
224240
return ParseResult::ErrorInvalidFormat;
@@ -276,8 +292,12 @@ ParseResult parse_latitude_coordinate(
276292
return ParseResult::ErrorOutOfRange;
277293
}
278294

279-
// Parse arcminutes
295+
// Parse arcminutes (must be exactly 2 digits, no trailing characters)
280296
std::string_view arcmin_part = str_nosign.substr(star_pos + 1);
297+
if (arcmin_part.size() != 2) {
298+
return ParseResult::ErrorInvalidFormat;
299+
}
300+
281301
uint32_t arcminutes;
282302
if (!parse_uint(arcmin_part.data(), 2, arcminutes)) {
283303
return ParseResult::ErrorInvalidFormat;
@@ -328,6 +348,9 @@ ParseResult parse_longitude_coordinate(
328348

329349
// Parse arcminutes
330350
std::string_view arcmin_part = str.substr(star_pos + 1);
351+
if (arcmin_part.size() != 2) {
352+
return ParseResult::ErrorInvalidFormat;
353+
}
331354
uint32_t arcminutes;
332355
if (!parse_uint(arcmin_part.data(), 2, arcminutes)) {
333356
return ParseResult::ErrorInvalidFormat;
@@ -387,6 +410,9 @@ ParseResult parse_time_value(
387410

388411
// Parse seconds
389412
std::string_view second_part = minute_part.substr(colon2_pos + 1);
413+
if (second_part.size() != 2) {
414+
return ParseResult::ErrorInvalidFormat;
415+
}
390416
uint32_t seconds;
391417
if (!parse_uint(second_part.data(), 2, seconds)) {
392418
return ParseResult::ErrorInvalidFormat;
@@ -447,6 +473,9 @@ ParseResult parse_date_value(
447473

448474
// Parse year
449475
std::string_view year_part = day_part.substr(slash2_pos + 1);
476+
if (year_part.size() != 2) {
477+
return ParseResult::ErrorInvalidFormat;
478+
}
450479
uint32_t year;
451480
if (!parse_uint(year_part.data(), 2, year)) {
452481
return ParseResult::ErrorInvalidFormat;

0 commit comments

Comments
 (0)