ubus: fix ubus announcements txt fields
authorAndrew Karpow <[email protected]>
Sun, 25 May 2025 04:02:39 +0000 (00:02 -0400)
committerFelix Fietkau <[email protected]>
Wed, 28 May 2025 22:28:43 +0000 (00:28 +0200)
The txt field of multicast dns is defined as an array of concatenated
length-values, where length is encoded in the first byte and value is a
non-NUL terminated string.
The ubus announcements callback tokenized the txt buffer by dividing
it between non-ASCII characters. This works fine for values with a
length <32 characters, but not for longer strings.
This patch correctly deserializes the txt values and removes the need
for dynamic allocation.

Signed-off-by: Andrew Karpow <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]> [minor cleanup]
ubus.c

diff --git a/ubus.c b/ubus.c
index 813db9ead7b3ed9619bcc602bb6120abe25e7dd4..49a4f67cd21e3af0572b25db79b80e2d8ba322d0 100644 (file)
--- a/ubus.c
+++ b/ubus.c
@@ -80,37 +80,27 @@ umdns_announcements(struct ubus_context *ctx, struct ubus_object *obj,
                // check if there are any text entries
                if (s->txt_len) {
                        void *c_txt = NULL;
-                       int i;
-
-                       // this string will hold text records
-                       char *txt_str = (char *) calloc(s->txt_len, sizeof(char));
-
-                       // we get some weird characters like \u000b, so get don't copy them
-                       for (i=0; i<s->txt_len; i++) {
-                               if ((ispunct(s->txt[i])) || (isalnum(s->txt[i])))
-                                       txt_str[i] = (char) s->txt[i];
-                               else
-                                       txt_str[i] = ' ';
-                       }
-
-                       txt_str[s->txt_len] = '\0';
+                       uint32_t txt_offset = 0;
+                       char *buf;
 
                        // a table of txt json objects
                        c_txt = blobmsg_open_array(&b, "txt");
 
-                       // split based on space and add each token to output
-                       char *pch = NULL, *pchr = NULL;
+                       while (txt_offset < s->txt_len) {
+                               uint8_t len = s->txt[txt_offset++];
+                               if (!len)
+                                       break;
+
+                               // copy to NUL-terminated string
+                               buf = blobmsg_alloc_string_buffer(&b, "txt", len + 1);
+                               strlcpy(buf, (const char *) &s->txt[txt_offset], len+1);
+                               blobmsg_add_string_buffer(&b);
 
-                       for (pch = strtok_r(txt_str, " ", &pchr); pch != NULL; pch = strtok_r(NULL, " ", &pchr)) {
-                               // add it to array
-                               blobmsg_add_string(&b, "txt", pch);
+                               txt_offset += len;
                        }
 
                        // close the array
                        blobmsg_close_array(&b, c_txt);
-
-                       // free the calloced memory
-                       free(txt_str);
                }
 
                blobmsg_close_table(&b, c2);