aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sway/ipc-server.c54
1 files changed, 32 insertions, 22 deletions
diff --git a/sway/ipc-server.c b/sway/ipc-server.c
index 22e0137b..ae758883 100644
--- a/sway/ipc-server.c
+++ b/sway/ipc-server.c
@@ -349,43 +349,53 @@ static int ipc_selection_data_cb(int fd, uint32_t mask, void *data) {
}
if (mask & WLC_EVENT_READABLE) {
- static const int step_size = 512;
- char *data = NULL;
- int ret = 0;
- int current = 0;
+ static const int max_size = 8192 * 1000;
+ int len = 512;
+ int i = 0;
+ char *buf = malloc(len);
// read data as long as there is data avilable
// grow the buffer step_size in every iteration
- do {
- if (data == NULL) {
- data = malloc(step_size);
- } else {
- data = realloc(data, current + step_size);
- }
+ for(;;) {
+ int amt = read(fd, buf + i, len - i - 1);
+ if (amt <= 0)
+ break;
+
+ i += amt;
+ if (i >= len - 1) {
+ if (len >= max_size) {
+ sway_log(L_ERROR, "selection data too large");
+ free(buf);
+ goto cleanup;
+ }
+ char *next = realloc(buf, (len *= 2));
+ if (!next) {
+ sway_log_errno(L_ERROR, "relloc failed");
+ free(buf);
+ goto cleanup;
+ }
- ret = read(fd, data + current, step_size - 1);
- if (ret < 0) {
- sway_log_errno(L_ERROR, "Reading from selection data fd failed");
- goto cleanup;
+ buf = next;
}
+ }
- current += ret;
- } while (ret == step_size - 1);
-
- data[current] = '\0';
+ buf[i] = '\0';
if (is_text_target(req->type)) {
json_object_object_add(req->json, req->type,
- json_object_new_string(data));
+ json_object_new_string(buf));
} else {
size_t outlen;
- char *b64 = b64_encode(data, current, &outlen);
- json_object_object_add(req->json, req->type,
+ char *b64 = b64_encode(buf, i, &outlen);
+ char *type = malloc(strlen(req->type) + 8);
+ strcat(type, ";base64");
+ json_object_object_add(req->json, type,
json_object_new_string(b64));
+ free(type);
free(b64);
}
- free(data);
+ free(buf);
}
cleanup: