On Tue, Sep 27, 2022 at 01:25:55PM -0500, Eric Blake wrote:
> On Tue, Sep 27, 2022 at 03:46:19PM +0100, Richard W.M. Jones wrote:
> > For API parameters that are pointers and must not be NULL, add the
> > appropriate GCC annotations.  These are only enabled in very recent
> > GCC (>= 12) because we have concerns with earlier versions, see for
> > example: https://bugzilla.redhat.com/show_bug.cgi?id=1041336
> > ---
> >  generator/C.ml | 52 ++++++++++++++++++++++++++++++++++++++++++++++++--
> >  1 file changed, 50 insertions(+), 2 deletions(-)
> 
> ACK 1 and 2 regardless of the rest of the series.
> 
> For this one...
> 
> > 
> > diff --git a/generator/C.ml b/generator/C.ml
> > index 013f81edf4..4f758e526f 100644
> > --- a/generator/C.ml
> > +++ b/generator/C.ml
> > @@ -107,6 +107,26 @@ let
> >    | UInt64 n -> [n]
> >    | UIntPtr n -> [n]
> >  
> > +let arg_attr_nonnull =
> > +  function
> > +  (* BytesIn/Out are passed using a non-null pointer, and size_t *)
> > +  | BytesIn _
> > +  | BytesOut _
> > +  | BytesPersistIn _
> > +  | BytesPersistOut _ -> [ true; false ]
> > +  (* sockaddr is also non-null pointer, and length *)
> > +  | SockAddrAndLen (n, len) -> [ true; false ]
> > +  (* strings should be marked as non-null *)
> > +  | Path _ | String _ -> [ true ]
> > +  (* list of strings should be marked as non-null *)
> > +  | StringList n -> [ true ]
> > +  (* other non-pointer types can never be null *)
> > +  | Bool _ | Closure _ | Enum _ | Fd _ | Flags _
> > +  | Int _ | Int64 _ | SizeT _
> > +  | UInt _ | UInt32 _ | UInt64 _ | UIntPtr _ -> [ false ]
> 
> It's a little bit odd to see UIntPtr called a 'non-pointer type' - but
> technically, it is an integer rather than a pointer.  And the clincher
> is that even if it represents a pointer, for our purposes it is an
> opaque type, and the user can indeed pass in NULL (cast to uintptr_t)
> and we should not complain.  So nothing wrong here other than maybe a
> confusing comment, although I don't have wording suggestions to help.
> 
> > @@ -216,7 +236,17 @@ let
> >  let print_fndecl ?wrap ?closure_style name args optargs ret =
> >    pr "extern ";
> >    print_call ?wrap ?closure_style name args optargs ret;
> > -  pr ";\n"
> > +
> > +  (* Non-null attribute. *)
> > +  let nns =
> > +    [ [ true ] ] (* for struct nbd_handle pointer *)
> > +    @ List.map arg_attr_nonnull args
> > +    @ List.map optarg_attr_nonnull optargs in
> > +  let nns : bool list = List.flatten nns in
> > +  let nns = List.mapi (fun i b -> (i+1, b)) nns in
> > +  let nns = filter_map (fun (i, b) -> if b then Some i else None) nns in
> > +  let nns : string list = List.map string_of_int nns in
> > +  pr "\n    LIBNBD_ATTRIBUTE_NONNULL((%s));\n" (String.concat "," nns)
> >
> 
> I'm still getting used to OCaml's ability to rebind a variable as many
> iterations as we want, even with different typing!  But this makes
> sense.

Some programmers will write it as:

  let nns = ... in
  let nns' = ... in
  let nns'' = ... in
  let nns''' = ... in

where the ' character is pronounced "prime".  Whether that's more or
less confusing I'll leave up to you to decide :-)

> > @@ -773,6 +814,13 @@ let
> >    pr "#include \"libnbd.h\"\n";
> >    pr "#include \"internal.h\"\n";
> >    pr "\n";
> > +  pr "/* We check that some string parameters declared as nonnull are\n";
> > +  pr " * not NULL.  This is intentional because we do not know if the\n";
> > +  pr " * calling compiler checked the attributes.  So ignore those\n";
> > +  pr " * warnings here.\n";
> > +  pr " */\n";
> > +  pr "#pragma GCC diagnostic ignored \"-Wnonnull-compare\"\n";
> 
> Does disabling the warning actually force the compiler to emit the
> nonnull check, or can it still be optimized away in spite of us
> silencing the warning?

So firstly this pragma is necessary in order to get rid of a warning
that would otherwise cause an error when using -Werror mode.  It only
disables the warning and GCC may still compile away the checks.

I checked the asm just now and ... it does appear to be getting rid of
the checks!  How annoying is that?

> Maybe we better off writing it so that for _this_ .c file, we
> pre-define LIBNBD_ATTRIBUTE_NONNULL() to be a no-op regardless of
> what the included .h files say.

Let me try something like that.

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
Fedora Windows cross-compiler. Compile Windows programs, test, and
build Windows installers. Over 100 libraries supported.
http://fedoraproject.org/wiki/MinGW
_______________________________________________
Libguestfs mailing list
Libguestfs@redhat.com
https://listman.redhat.com/mailman/listinfo/libguestfs

Reply via email to