diff --git a/modules/libcom/src/misc/epicsString.c b/modules/libcom/src/misc/epicsString.c index 951c65606..6df10c3a6 100644 --- a/modules/libcom/src/misc/epicsString.c +++ b/modules/libcom/src/misc/epicsString.c @@ -83,38 +83,40 @@ int epicsStrnRawFromEscaped(char *dst, size_t dstlen, const char *src, if (!srclen-- || !(c = *src++)) { OUT(u); goto done; } - if (c < '0' || c > '7') { + if (c < '0' || c > '7' || u > 037) { OUT(u); goto input; } u = u << 3 | (c - '0'); - - if (u > 0377) { - /* Undefined behaviour! */ - } OUT(u); } break; case 'x' : - { /* \xXXX... */ + { /* \xXX */ unsigned int u = 0; if (!srclen-- || !(c = *src++ & 0xff)) goto done; - while (isxdigit(c)) { - u = u << 4 | ((c > '9') ? toupper(c) - 'A' + 10 : c - '0'); - if (u > 0xff) { - /* Undefined behaviour! */ - } - if (!srclen-- || !(c = *src++ & 0xff)) { - OUT(u); - goto done; - } + if (!isxdigit(c)) + goto input; + + u = u << 4 | ((c > '9') ? toupper(c) - 'A' + 10 : c - '0'); + + if (!srclen-- || !(c = *src++ & 0xff)) { + OUT(u); + goto done; } + + if (!isxdigit(c)) { + OUT(u); + goto input; + } + + u = u << 4 | ((c > '9') ? toupper(c) - 'A' + 10 : c - '0'); OUT(u); - goto input; } + break; default: OUT(c); diff --git a/modules/libcom/test/epicsStringTest.c b/modules/libcom/test/epicsStringTest.c index 8bd1d5baa..0f1537f97 100644 --- a/modules/libcom/test/epicsStringTest.c +++ b/modules/libcom/test/epicsStringTest.c @@ -88,7 +88,7 @@ MAIN(epicsStringTest) char *s; int status; - testPlan(406); + testPlan(416); testChars(); @@ -257,6 +257,19 @@ MAIN(epicsStringTest) testOk(result[0] == 0123, " Octal escape (got \\%03o)", result[0]); testOk(result[status] == 0, " 0-terminated"); + memset(result, 'x', sizeof(result)); + status = epicsStrnRawFromEscaped(result, 4, "\\377", 4); + testOk(status == 1, "raw(\"\\377\", 4) -> %d (exp. 1)", status); + testOk((result[0] & 0xff) == 0377, " Octal escape (got \\%03o)", result[0]); + testOk(result[status] == 0, " 0-terminated"); + + memset(result, 'x', sizeof(result)); + status = epicsStrnRawFromEscaped(result, 4, "\\400", 4); + testOk(status == 2, "raw(\"\\400\", 4) -> %d (exp. 2)", status); + testOk(result[0] == 040, " Octal escape (got \\%03o)", result[0]); + testOk(result[1] == '0', " Terminator char got '%c'", result[1]); + testOk(result[status] == 0, " 0-terminated"); + memset(result, 'x', sizeof(result)); status = epicsStrnRawFromEscaped(result, 4, "\\812", 2); testOk(status == 1, "raw(\"\\812\", 2) -> %d (exp. 1)", status); @@ -307,14 +320,17 @@ MAIN(epicsStringTest) memset(result, 'x', sizeof(result)); status = epicsStrnRawFromEscaped(result, 4, "\\x012", 5); - testOk(status == 1, "raw(\"\\x012\", 5) -> %d (exp. 1)", status); - testOk(result[0] == 0x12," Hex escape (got \\x%x)", result[0]); + testOk(status == 2, "raw(\"\\x012\", 5) -> %d (exp. 2)", status); + testOk(result[0] == 0x1," Hex escape (got \\x%x)", result[0]); + testOk(result[1] == '2', " Terminator char got '%c'", result[1]); testOk(result[status] == 0, " 0-terminated"); memset(result, 'x', sizeof(result)); status = epicsStrnRawFromEscaped(result, 4, "\\x0012", 6); - testOk(status == 1, "raw(\"\\x0012\", 6) -> %d (exp. 1)", status); - testOk(result[0] == 0x12," Hex escape (got \\x%x)", result[0]); + testOk(status == 3, "raw(\"\\x0012\", 6) -> %d (exp. 3)", status); + testOk(result[0] == 0," Hex escape (got \\x%x)", result[0]); + testOk(result[1] == '1', " Terminator char got '%c'", result[1]); + testOk(result[2] == '2', " Following char got '%c'", result[2]); testOk(result[status] == 0, " 0-terminated"); memset(result, 'x', sizeof(result));