lua: Fix stack imbalance in ubus_event_handler
[project/ubus.git] / libubus-io.c
index 3280e41..9d3ac6c 100644 (file)
@@ -11,6 +11,7 @@
  * GNU General Public License for more details.
  */
 
+#define _GNU_SOURCE
 #include <sys/types.h>
 #include <sys/uio.h>
 #include <sys/socket.h>
@@ -231,6 +232,36 @@ static bool ubus_validate_hdr(struct ubus_msghdr *hdr)
        return true;
 }
 
+static bool alloc_msg_buf(struct ubus_context *ctx, int len)
+{
+       void *ptr;
+       int buf_len = ctx->msgbuf_data_len;
+       int rem;
+
+       if (!ctx->msgbuf.data)
+               buf_len = 0;
+
+       rem = (len % UBUS_MSG_CHUNK_SIZE);
+       if (rem > 0)
+               len += UBUS_MSG_CHUNK_SIZE - rem;
+
+       if (len < buf_len &&
+           ++ctx->msgbuf_reduction_counter > UBUS_MSGBUF_REDUCTION_INTERVAL) {
+               ctx->msgbuf_reduction_counter = 0;
+               buf_len = 0;
+       }
+
+       if (len <= buf_len)
+               return true;
+
+       ptr = realloc(ctx->msgbuf.data, len);
+       if (!ptr)
+               return false;
+
+       ctx->msgbuf.data = ptr;
+       return true;
+}
+
 static bool get_next_msg(struct ubus_context *ctx, int *recv_fd)
 {
        struct {
@@ -254,23 +285,7 @@ static bool get_next_msg(struct ubus_context *ctx, int *recv_fd)
                return false;
 
        len = blob_raw_len(&hdrbuf.data);
-       if (len > ctx->msgbuf_data_len) {
-               ctx->msgbuf_reduction_counter = UBUS_MSGBUF_REDUCTION_INTERVAL;
-       } else if (ctx->msgbuf_data_len > UBUS_MSG_CHUNK_SIZE) {
-               if (ctx->msgbuf_reduction_counter > 0) {
-                       len = -1;
-                       --ctx->msgbuf_reduction_counter;
-               } else
-                       len = UBUS_MSG_CHUNK_SIZE;
-       } else
-               len = -1;
-
-       if (len > -1) {
-               ctx->msgbuf.data = realloc(ctx->msgbuf.data, len * sizeof(char));
-               if (ctx->msgbuf.data)
-                       ctx->msgbuf_data_len = len;
-       }
-       if (!ctx->msgbuf.data)
+       if (!alloc_msg_buf(ctx, len))
                return false;
 
        memcpy(&ctx->msgbuf.hdr, &hdrbuf.hdr, sizeof(hdrbuf.hdr));
@@ -287,11 +302,10 @@ static bool get_next_msg(struct ubus_context *ctx, int *recv_fd)
 void __hidden ubus_handle_data(struct uloop_fd *u, unsigned int events)
 {
        struct ubus_context *ctx = container_of(u, struct ubus_context, sock);
-       struct ubus_msghdr *hdr = &ctx->msgbuf.hdr;
        int recv_fd = -1;
 
        while (get_next_msg(ctx, &recv_fd)) {
-               ubus_process_msg(ctx, hdr, recv_fd);
+               ubus_process_msg(ctx, &ctx->msgbuf, recv_fd);
                if (uloop_cancelled)
                        break;
        }