aboutsummaryrefslogtreecommitdiff
path: root/client/acronc/handler_stdin.c
diff options
context:
space:
mode:
authorTrumeet <yuuta@yuuta.moe>2022-07-26 21:27:24 -0700
committerTrumeet <yuuta@yuuta.moe>2022-07-26 21:27:24 -0700
commitc6948fd983fa1855b2dadba50aa50f576f54bdda (patch)
treec673a57580e8a87f4ce5dc6acd9763393e667ee0 /client/acronc/handler_stdin.c
parentf635018a3309b1cdddd6546b50f0a18214899218 (diff)
downloadacron-c6948fd983fa1855b2dadba50aa50f576f54bdda.tar
acron-c6948fd983fa1855b2dadba50aa50f576f54bdda.tar.gz
acron-c6948fd983fa1855b2dadba50aa50f576f54bdda.tar.bz2
acron-c6948fd983fa1855b2dadba50aa50f576f54bdda.zip
fix(acronc): input <cmd><EOF> will cause illegal memory access
Cause: 1. stdin got cmd -> request 2. stdin got EOF -> ac_disconnect -> ac_conn becomes NULL 3. socket got response -> ac_receive(ac_conn) -> crash Conclusion: ordering issue between ac_disconnect and socket read. Solution: Best way: pause the input until command returns Cons: 1. Lost the advantage of background execution of commands (has to wait until done) 2. It is unreliable to determine if a command is done: although the current server implementation will not send anything else after an error or cmd_result, Minecraft server itself or future server implementations may. The spec does not say anything on termination. Acronc currently assumes that after receiving an error or cmd_result with the same request ID, it is done. Then, it resumes the stdin, reads the EOF, and then disconnect. Worse way: Directly call uv_read_stop before ac_disconnect Cons: It is going to lose anything, including command results. This is particularly undesirable for ad-hoc calls (i.e. echo list | acronc). Therefore, the current approach is to block and read as much as we can (until error or cmd_result), then stop reading the socket before disconnecting as a double safe. Signed-off-by: Trumeet <yuuta@yuuta.moe>
Diffstat (limited to 'client/acronc/handler_stdin.c')
-rw-r--r--client/acronc/handler_stdin.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/client/acronc/handler_stdin.c b/client/acronc/handler_stdin.c
index 3ac307d..4b8d0b8 100644
--- a/client/acronc/handler_stdin.c
+++ b/client/acronc/handler_stdin.c
@@ -74,12 +74,20 @@ static void on_stdin(uv_stream_t *t, ssize_t nread, const uv_buf_t *buf) {
free(buf->base);
}
+int stdin_start(void) {
+ return uv_read_start((uv_stream_t *) &tty, on_alloc, on_stdin);
+}
+
+void stdin_stop(void) {
+ uv_read_stop((uv_stream_t *) &tty);
+}
+
int h_stdin(int (*on_input)(ac_request_t *req),
void (*on_close)(void)) {
cb_recv = on_input;
cb_close = on_close;
int r;
if ((r = uv_tty_init(loop, &tty, 0, 0))) return r;
- if ((r = uv_read_start((uv_stream_t *) &tty, on_alloc, on_stdin))) return r;
+ if ((r = stdin_start())) return r;
return 0;
} \ No newline at end of file