core: accept NULL consumer strings
authorBartosz Golaszewski <bartekgola@gmail.com>
Wed, 12 Jul 2017 17:46:50 +0000 (19:46 +0200)
committerBartosz Golaszewski <bartekgola@gmail.com>
Wed, 12 Jul 2017 18:07:00 +0000 (20:07 +0200)
If the user passes a NULL pointer as the consumer name to any of the
line request functions, pass an empty string to the kernel instead of
segfaulting. The kernel code will then set the consumer string to "?".

Signed-off-by: Bartosz Golaszewski <bartekgola@gmail.com>
src/lib/core.c
tests/tests-line.c

index 8b00b18353d073b7baf768bcb9d74cf248bdeac8..3fba33d957e61021d5f4b9fef3a079fc577486fb 100644 (file)
@@ -316,8 +316,9 @@ static int line_request_values(struct gpiod_line_bulk *bulk,
                        req->default_values[i] = !!default_vals[i];
        }
 
-       strncpy(req->consumer_label, config->consumer,
-               sizeof(req->consumer_label) - 1);
+       if (config->consumer)
+               strncpy(req->consumer_label, config->consumer,
+                       sizeof(req->consumer_label) - 1);
 
        fd = bulk->lines[0]->chip->fd;
 
@@ -345,8 +346,11 @@ static int line_request_event_single(struct gpiod_line *line,
        req = &line->event;
 
        memset(req, 0, sizeof(*req));
-       strncpy(req->consumer_label, config->consumer,
-               sizeof(req->consumer_label) - 1);
+
+       if (config->consumer)
+               strncpy(req->consumer_label, config->consumer,
+                       sizeof(req->consumer_label) - 1);
+
        req->lineoffset = gpiod_line_offset(line);
        req->handleflags |= GPIOHANDLE_REQUEST_INPUT;
 
index b0a07bfecce4fc4cbe7bd9742a03ec7f64392d62..fab299823d3713ecb6c893e107cadccc43343ebf 100644 (file)
@@ -396,3 +396,41 @@ static void line_misc_flags(void)
 TEST_DEFINE(line_misc_flags,
            "gpiod_line - misc flags",
            0, { 8 });
+
+static void line_null_consumer(void)
+{
+       TEST_CLEANUP(test_close_chip) struct gpiod_chip *chip = NULL;
+       struct gpiod_line_request_config config;
+       struct gpiod_line *line;
+       int rv;
+
+       chip = gpiod_chip_open(test_chip_path(0));
+       TEST_ASSERT_NOT_NULL(chip);
+
+       line = gpiod_chip_get_line(chip, 2);
+       TEST_ASSERT_NOT_NULL(line);
+
+       config.request_type = GPIOD_REQUEST_DIRECTION_INPUT;
+       config.consumer = NULL;
+       config.active_state = GPIOD_REQUEST_ACTIVE_HIGH;
+       config.flags = 0;
+
+       rv = gpiod_line_request(line, &config, 0);
+       TEST_ASSERT_RET_OK(rv);
+       TEST_ASSERT_STR_EQ(gpiod_line_consumer(line), "?");
+
+       gpiod_line_release(line);
+
+       /*
+        * Internally we use different structures for event requests, so we
+        * need to test that explicitly too.
+        */
+       config.request_type = GPIOD_REQUEST_EVENT_BOTH_EDGES;
+
+       rv = gpiod_line_request(line, &config, 0);
+       TEST_ASSERT_RET_OK(rv);
+       TEST_ASSERT_STR_EQ(gpiod_line_consumer(line), "?");
+}
+TEST_DEFINE(line_null_consumer,
+           "line request - NULL consumer string",
+           0, { 8 });