Fixed the response of epicsStrnRawFromEscaped() to numeric overflows

\x only takes 2 hex digits now, and the octal parser ignores a 3rd
digit if it would take the value over 0xff:
    "\400"  => ' ' then '0'
    "\x088" => '\b' then '8'

With additional tests.
This commit is contained in:
Andrew Johnson
2020-08-09 00:33:07 -05:00
parent 0c800d4428
commit 8c9e42d15e
2 changed files with 39 additions and 21 deletions
+18 -16
View File
@@ -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);
+21 -5
View File
@@ -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));