diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp index 640b6df25..d7fd025f9 100644 --- a/libsysutils/src/FrameworkListener.cpp +++ b/libsysutils/src/FrameworkListener.cpp @@ -33,7 +33,8 @@ bool FrameworkListener::onDataAvailable(SocketClient *c) { char buffer[255]; int len; - if ((len = read(c->getSocket(), buffer, sizeof(buffer) -1)) < 0) { + len = TEMP_FAILURE_RETRY(read(c->getSocket(), buffer, sizeof(buffer))); + if (len < 0) { SLOGE("read() failed (%s)", strerror(errno)); return false; } else if (!len) @@ -44,6 +45,7 @@ bool FrameworkListener::onDataAvailable(SocketClient *c) { for (i = 0; i < len; i++) { if (buffer[i] == '\0') { + /* IMPORTANT: dispatchCommand() expects a zero-terminated string */ dispatchCommand(c, buffer + offset); offset = i + 1; } @@ -62,6 +64,7 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { char tmp[255]; char *p = data; char *q = tmp; + char *qlimit = tmp + sizeof(tmp) - 1; bool esc = false; bool quote = false; int k; @@ -71,6 +74,8 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { while(*p) { if (*p == '\\') { if (esc) { + if (q >= qlimit) + goto overflow; *q++ = '\\'; esc = false; } else @@ -78,11 +83,15 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { p++; continue; } else if (esc) { - if (*p == '"') + if (*p == '"') { + if (q >= qlimit) + goto overflow; *q++ = '"'; - else if (*p == '\\') + } else if (*p == '\\') { + if (q >= qlimit) + goto overflow; *q++ = '\\'; - else { + } else { cli->sendMsg(500, "Unsupported escape sequence", false); goto out; } @@ -100,9 +109,13 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { continue; } + if (q >= qlimit) + goto overflow; *q = *p++; if (!quote && *q == ' ') { *q = '\0'; + if (argc >= CMD_ARGS_MAX) + goto overflow; argv[argc++] = strdup(tmp); memset(tmp, 0, sizeof(tmp)); q = tmp; @@ -111,6 +124,9 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { q++; } + *q = '\0'; + if (argc >= CMD_ARGS_MAX) + goto overflow; argv[argc++] = strdup(tmp); #if 0 for (k = 0; k < argc; k++) { @@ -122,7 +138,7 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { cli->sendMsg(500, "Unclosed quotes error", false); goto out; } - + for (i = mCommands->begin(); i != mCommands->end(); ++i) { FrameworkCommand *c = *i; @@ -140,4 +156,8 @@ out: for (j = 0; j < argc; j++) free(argv[j]); return; + +overflow: + cli->sendMsg(500, "Command too long", false); + goto out; }