Skip to content

Commit 92ae2f9

Browse files
Stricter tests on territories and illegal characters
1 parent c9e9c4d commit 92ae2f9

File tree

1 file changed

+29
-16
lines changed

1 file changed

+29
-16
lines changed

mapcodelib/mapcoder.c

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ static int disambiguate_str(const char *s, int len) // returns disambiguation 1-
185185
}
186186

187187

188+
#ifndef FAST_ALPHA
188189
// returns coode, or negative if invalid
189190
static int ccode_of_iso3(const char *in_iso, int parentcode) {
190191
const char *aliases = ALIASES;
@@ -196,12 +197,14 @@ static int ccode_of_iso3(const char *in_iso, int parentcode) {
196197
if (in_iso[2]) {
197198
if (in_iso[2] == '-') {
198199
parentcode = disambiguate_str(in_iso, 2);
199-
hyphenated = (parentcode > 0);
200+
if (parentcode < 0) { return parentcode; }
201+
hyphenated = 1;
200202
in_iso += 3;
201203
}
202204
else if (in_iso[3] == '-') {
203205
parentcode = disambiguate_str(in_iso, 3);
204-
hyphenated = (parentcode > 0);
206+
if (parentcode < 0) { return parentcode; }
207+
hyphenated = 1;
205208
in_iso += 4;
206209
}
207210
}
@@ -211,11 +214,12 @@ static int ccode_of_iso3(const char *in_iso, int parentcode) {
211214
iso[0] = (char) toupper(in_iso[0]);
212215
if (iso[0]) { iso[1] = (char) toupper(in_iso[1]); }
213216
if (iso[1]) { iso[2] = (char) toupper(in_iso[2]); }
217+
if (iso[2] && in_iso[3]!=0 && in_iso[3]!='-') { return -41; }
214218
iso[3] = 0;
215219

216220
if (iso[2] == 0 || iso[2] == ' ') // 2-letter iso code?
217221
{
218-
static char disambiguate_iso3[4] = {'1', '?', '?', 0}; // cache for disambiguation
222+
static char disambiguate_iso3[4] = {'0', '?', '?', 0}; // cache for disambiguation
219223
if (parentcode > 0) {
220224
disambiguate_iso3[0] = (char) ('0' + parentcode);
221225
}
@@ -227,7 +231,7 @@ static int ccode_of_iso3(const char *in_iso, int parentcode) {
227231
s = strstr(aliases, disambiguate_iso3); // search in aliases
228232
if (s == NULL || s[3] != '=') {
229233
s = NULL;
230-
if (disambiguate_iso3[0] <= '9') {
234+
if (disambiguate_iso3[0] <= '9' && !hyphenated) {
231235
disambiguate_iso3[0] = '0';
232236
s = strstr(aliases, disambiguate_iso3); // search in aliases
233237
}
@@ -237,7 +241,7 @@ static int ccode_of_iso3(const char *in_iso, int parentcode) {
237241
s = strstr(entity_iso, iso); // search disambiguated 2-letter iso
238242
}
239243
}
240-
if (s == NULL) {
244+
if (s == NULL && !hyphenated) {
241245
// find the FIRST disambiguation option, if any
242246
for (s = entity_iso - 1; ;) {
243247
s = strstr(s + 1, disambiguate_iso3 + 1);
@@ -293,7 +297,7 @@ static int ccode_of_iso3(const char *in_iso, int parentcode) {
293297
// return result
294298
return (int) ((s - entity_iso) / 4);
295299
}
296-
300+
#endif
297301

298302
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
299303
//
@@ -357,6 +361,9 @@ static int decodeExtension(decodeRec *dec, int dividerx4, int dividery0, int lon
357361
int lat32 = 0;
358362
int processor = 1;
359363
int odd = 0;
364+
if (strlen(extrapostfix)>MAX_PRECISION_DIGITS) {
365+
return -79; // too many digits
366+
}
360367
while (*extrapostfix) {
361368
int column1, row1, column2, row2;
362369
int c1 = *extrapostfix++;
@@ -978,8 +985,8 @@ static void repack_if_alldigits(char *input, int aonly) {
978985
}
979986
}
980987

981-
static int unpack_if_alldigits(
982-
char *input) // returns 1 if unpacked, 0 if left unchanged, negative if unchanged and an error was detected
988+
// returns 1 if unpacked, 0 if left unchanged, negative if unchanged and an error was detected
989+
static int unpack_if_alldigits(char *input)
983990
{ // rewrite all-digit codes
984991
char *s = input;
985992
char *dotpos = NULL;
@@ -1029,6 +1036,8 @@ static int unpack_if_alldigits(
10291036
if (v < 100) {
10301037
*s = encode_chars[(unsigned int) v / 10];
10311038
*e = encode_chars[(unsigned int) v % 10];
1039+
} else {
1040+
return -31; // overflow (ending in UE or UU)
10321041
}
10331042
return 1;
10341043
}
@@ -1397,22 +1406,22 @@ static int decoderEngine(decodeRec *dec) {
13971406
if (s) {
13981407
*s++ = 0;
13991408
while (*s > 0 && *s <= 32) { s++; }
1400-
ccode = ccode_of_iso3(w, dec->context);
1409+
ccode = convertTerritoryIsoNameToCode(w, dec->context-1) - 1;
14011410
}
14021411
else {
14031412
ccode = dec->context - 1;
14041413
s = w;
14051414
}
14061415
if (ccode == ccode_mex && len < 8) {
1407-
ccode = ccode_of_iso3("5MX", -1);
1416+
ccode = convertTerritoryIsoNameToCode("5MX", -1) - 1;
14081417
} // special case for mexico country vs state
14091418
if (*s=='u' || *s=='U') {
14101419
strcpy(s,s+1);
14111420
repack_if_alldigits(s, 1);
14121421
}
14131422
dec->context = ccode;
14141423
dec->mapcode = s;
1415-
dec->extension = "";
1424+
dec->extension = NULL;
14161425
// make upper, handle i and o, split off high precision characters if any
14171426
for (w = s; *w != 0; w++) {
14181427
// uppercase
@@ -1427,7 +1436,7 @@ static int decoderEngine(decodeRec *dec) {
14271436
*w = '1';
14281437
} else if (*w == 'A' || *w == 'E' || *w == 'U') {
14291438
hasvowels = 1;
1430-
} else {
1439+
} else if (dec->extension == NULL) {
14311440
hasletters = 1;
14321441
}
14331442
}
@@ -1438,9 +1447,9 @@ static int decoderEngine(decodeRec *dec) {
14381447
prelen = (int) ((dot = w) - s);
14391448
}
14401449
else if (*w == '-') {
1441-
if (*dec->extension) {
1442-
return -17;
1443-
} // already had a hyphen
1450+
if (dec->extension != NULL) {
1451+
return -17; // already had a hyphen
1452+
}
14441453
dec->extension = w + 1;
14451454
*w = 0;
14461455
}
@@ -1451,6 +1460,9 @@ static int decoderEngine(decodeRec *dec) {
14511460
if (!dot) {
14521461
return -27;
14531462
}
1463+
if (dec->extension == NULL) {
1464+
dec->extension = "";
1465+
}
14541466

14551467
codex = prelen * 10 + strlen(dot) - 1;
14561468

@@ -1642,7 +1654,7 @@ static int decoderEngine(decodeRec *dec) {
16421654
#ifdef SUPPORT_FOREIGN_ALPHABETS
16431655

16441656
// WARNING - these alphabets have NOT yet been released as standard! use at your own risk! check www.mapcode.com for details.
1645-
static UWORD asc2lan[MAX_LANGUAGES][36] = // A-Z equivalents for ascii characters A to Z, 0-9
1657+
static UWORD asc2lan[MAPCODE_ALPHABETS_TOTAL][36] = // A-Z equivalents for ascii characters A to Z, 0-9
16461658
{
16471659
{0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039}, // roman
16481660
{0x0391, 0x0392, 0x039e, 0x0394, 0x003f, 0x0395, 0x0393, 0x0397, 0x0399, 0x03a0, 0x039a, 0x039b, 0x039c, 0x039d, 0x039f, 0x03a1, 0x0398, 0x03a8, 0x03a3, 0x03a4, 0x003f, 0x03a6, 0x03a9, 0x03a7, 0x03a5, 0x0396, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039}, // greek
@@ -2118,6 +2130,7 @@ int decodeMapcodeToLatLon(double *lat, double *lon, const char *input,
21182130

21192131
#ifdef SUPPORT_FOREIGN_ALPHABETS
21202132

2133+
// convert as much as will fit of mapcode into unibuf
21212134
UWORD *convertToAlphabet(UWORD *unibuf, int maxlength, const char *mapcode, int alphabet) // 0=roman, 2=cyrillic
21222135
{
21232136
UWORD *startbuf = unibuf;

0 commit comments

Comments
 (0)