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:
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user