On 02/01/22 20:44, Eric Blake wrote:
This example failed to check the *error parameter to the read and
write completion callbacks. What's more, the buffers start life
uninitialized, so a failed read can end up leaking heap contents to
the corresponding write.
Fortunately, the example program is hard-coded to two particular
nbdkit invocations, and not usable to corrupt a user's data. However,
as this example is likely to be copied elsewhere, we should at least
perform rudimentary error checking to avoid bad copy-and-paste that
could turn into a more severe problem in code derived from this.
Easiest for the example is to just punt and exit the process on any
detected errors from either the source or destination.
Since the nbdkit invocations are hard-coded, testing that this patch
works involves using a temporary patch, such as:
| diff --git i/examples/glib-main-loop.c w/examples/glib-main-loop.c
| index 1982f941..f60a4a38 100644
| --- i/examples/glib-main-loop.c
| +++ w/examples/glib-main-loop.c
| @@ -232,7 +232,8 @@ static struct NBDSource *gssrc, *gsdest;
| #define SIZE (1024*1024*1024)
|
| static const char *src_args[] = {
| - "nbdkit", "-s", "--exit-with-parent", "-r",
"pattern", "size=1G", NULL
| + "nbdkit", "-s", "--exit-with-parent", "-r",
"--filter=error",
| + "pattern", "size=1G", "error-pread-rate=0.1", NULL
| };
|
| static const char *dest_args[] = {
Fixes: bc3b4230 ("examples: Include an example of integrating with the glib main
loop", v0.1.9)
---
examples/glib-main-loop.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/examples/glib-main-loop.c b/examples/glib-main-loop.c
index 2df27878..1982f941 100644
--- a/examples/glib-main-loop.c
+++ b/examples/glib-main-loop.c
@@ -402,6 +402,11 @@ finished_read (void *vp, int *error)
if (gssrc == NULL)
return 1; /* Nothing we can do, auto-retire the callback */
+ if (*error) {
+ fprintf (stderr, "finished_read: read failed: %s\n", strerror (*error));
+ exit (EXIT_FAILURE);
+ }
+
DEBUG (gssrc, "finished_read: read completed");
assert (buffer->state == BUFFER_READING);
@@ -448,6 +453,11 @@ finished_write (void *vp, int *error)
if (gsdest == NULL)
return 1; /* Nothing we can do, auto-retire the callback */
+ if (*error) {
+ fprintf (stderr, "finished_write: write failed: %s\n", strerror
(*error));
+ exit (EXIT_FAILURE);
+ }
+
DEBUG (gsdest, "finished_write: write completed");
assert (buffer->state == BUFFER_WRITING);
Slightly inconsistent with
+ errno = *error;
+ perror ("failed to read");
+ exit (EXIT_FAILURE);
from the first patch, but does effectively the same thing.
Thanks,
Laszlo