In the C API documentation mention the potential problems of calling
non-nullable parameters with NULL. Usually an error is returned, but
warnings and worse might happen too.
Thanks: Eric Blake
Acked-by: Laszlo Ersek <lersek(a)redhat.com>
---
docs/libnbd.pod | 18 ++++++++++++++++++
generator/C.ml | 21 +++++++++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/docs/libnbd.pod b/docs/libnbd.pod
index eae9bb413b..170fc1fa07 100644
--- a/docs/libnbd.pod
+++ b/docs/libnbd.pod
@@ -387,8 +387,26 @@ The library ran out of memory while performing some operation.
A request is too large, for example if you try to read too many bytes
in a single L<nbd_pread(3)> call.
+=item C<EFAULT>
+
+A pointer parameter was C<NULL> when it should be non-NULL.
+See the section below.
+
=back
+=head2 Non-NULL parameters
+
+Almost all libnbd functions when called from C take one or more
+pointer parameters that must not be C<NULL>. For example, the handle
+parameter, strings and buffers should usually not be C<NULL>.
+
+If a C<NULL> is passed as one of these parameters, libnbd attempts to
+return an error with L<nbd_get_errno(3)> returning C<EFAULT>.
+
+However it may cause other compiler-related warnings and even
+undefined behaviour, so you should try to avoid this programming
+mistake.
+
=head1 DEBUGGING MESSAGES
Libnbd can print lots of debugging messages, useful if you have a
diff --git a/generator/C.ml b/generator/C.ml
index 2f22ad1e59..7d4bf7d509 100644
--- a/generator/C.ml
+++ b/generator/C.ml
@@ -107,6 +107,11 @@ let
| UInt64 n -> [n]
| UIntPtr n -> [n]
+let name_of_optarg =
+ function
+ | OClosure { cbname } -> cbname
+ | OFlags (n, _, _) -> n
+
(* Map function arguments to __attribute__((nonnull)) annotations.
* Because a single arg may map to multiple C parameters this
* returns a list. Note: true => add attribute nonnull.
@@ -980,6 +985,7 @@ let
pr "=head1 ERRORS\n";
pr "\n";
+
if may_set_error then (
let value = match errcode with
| Some value -> value
@@ -993,6 +999,21 @@ let
pr "This function does not fail.\n";
pr "\n";
+ pr "The following parameters must not be NULL: C<h>";
+ List.iter (
+ fun arg ->
+ let nns = arg_attr_nonnull arg in
+ if List.mem true nns then pr ", C<%s>" (List.hd (name_of_arg arg))
+ ) args;
+ List.iter (
+ fun arg ->
+ let nns = optarg_attr_nonnull arg in
+ if List.mem true nns then pr ", C<%s>" (name_of_optarg arg)
+ ) optargs;
+ pr ".\n";
+ pr "For more information see L<libnbd(3)/Non-NULL parameters>.\n";
+ pr "\n";
+
if permitted_states <> [] then (
pr "=head1 HANDLE STATE\n";
pr "\n";
--
2.37.0.rc2