Reordering new API's that have a libctx, propq

Nicola Tuveri nic.tuv at
Sat Sep 5 10:44:51 UTC 2020

On Sat, Sep 5, 2020, 12:13 Tim Hudson <tjh at> wrote:

> On Sat, Sep 5, 2020 at 6:38 PM Nicola Tuveri <nic.tuv at> wrote:
>> In most (if not all) cases in our functions, both libctx and propquery
>> are optional arguments, as we have global defaults for them based on the
>> loaded config file.
>> As such, explicitly passing non-NULL libctx and propquery, is likely to
>> be an exceptional occurrence rather than the norm.
> And that is where we have a conceptual difference, the libctx is *always* used.
> If it is provided as a NULL parameter then it is a shortcut to make the
> call to get the default or to get the already set one.
> Conceptually it is always required for the function to operate.
> And the conceptual issue is actually important here - all of these
> functions require the libctx to do their work - if it is not available then
> they are unable to do their work.
> We just happen to have a default-if-NULL.
> If C offered the ability to default a parameter if not provided (and many
> languages offer that) I would expect we would be using it.
> But it doesn't - we are coding in C.
> So it is really where-is-what-this-function-needs-coming-from that
> actually is the important thing - the source of the information the
> function needs to make its choice.
> It isn't which algorithm is being selected - the critical thing is from
> which pool of algorithm implementations are we operating. The pool must be
> specified (this is C code), but we have a default value.
> And that is why I think the conceptual approach here is getting confused
> by the arguments appearing to be optional - conceptually they are not - we
> just have a defaulting mechanism and that isn't the same conceptually as
> the arguments actually being optional.
> Clearer?

It's not yet clear to me the distinction you are trying to make.

I'll try to spell out what I extrapolated from your answer, and I apologize
in advance if I am misunderstanding your argument, please be patient and
correct me in that case so I can better understand your point!

It seems to me you are making a conceptual difference between
- a function that internally requires an instance of foo to work (and has a
default if foo is given as NULL among the arguments); e.g libctx is
necessary for a fetch, if a NULL libctx is given a mechanism is in place to
retrieve the global default one
- a function that internally uses an instance of foo only if a non-NULL one
is passed as argument; e.g. bnctx, if the user provides it this is used by
the callee and passed to its callee, if the user passes NULL the function
creates a fresh one for itself and/or its callees

But as a consumer of the API that difference is not visible and probably
not even interesting, as we are programming in C and passing pointers,
there are certain arguments that are required and must be passed as valid
pointers, others that appear optional because as a consumer of that API I
can pass NULL and let the function internally default to a reasonable
behavior (and whatever this "reasonable behavior" is — whether the first or
the second case from above, or another one I did not list —, it's part of
the documentation of that API).

IMHO, in the consumer POV, libctx and propq are optional arguments (even in
C where optional or default arguments do not technically exist and the
caller needs to always specify a value for each argument, which are always
positional) in the sense that they can pass NULL as a value rather than a
pointer to a fully instantiated object of the required type.
Even more so given that, excluding a minority of cases, we can expect
consumers of the APIs taking libctx and propq as arguments to pass NULL for
both of them and rely on the openssl config mechanism.

So while I agree with Tim that sometime it is valuable to make a difference
among the consequences of passing NULL as arguments in the context of one
kind of function and another, I believe the place for that is the
documentation not its signature.
The signature of the function should be designed for consumer usability,
and the conventional pattern there seems to be
- required args
- optional args
- callback+cb_args
and inside each group the "importance" factor should be the secondary
sorting criteria.

"importance" is probably going to be affected by the difference you are
making (or my understanding of it): e.g. if a function took both libctx and
bnctx, the fact that a valid pre-existing libctx is required to work (and a
global already existing one will be retrieved in case none is given), while
a fresh short-lived bnctx is going to be created only for the lifetime of
the called function in case none is given seems to indicate that libctx is
of vital importance for the API functionality, while bnctx is of minor

But... going this way as a generalized approach, would bring us to the "add
in the middle" scenario that we'd like to avoid.
I recognize that this is a point you already made in your original writeup,
as the tendency of "add to the end" to naturally degrade into "add in the

So, my question is: if "degradable add to the end" (where "degradable" only
happens rarely and for good reasons) seems the one that in the end produces
signatures matching (IMHO) the conventional usability patterns expected by
consumers of the API, is it such a dramatic conclusion that we want to
exclude it?

Or is your point that we are writing in C, all the arguments are
positional, none is ever really optional, there is no difference between
passing a `(void*) NULL` or a valid `(TYPE*) ptr` as the value of a `TYPE
*` argument, so "importance" is the only remaining sorting criteria, hence
(libctx, propq) are always the most important and should go to the
beginning of the args list (with the exception of the `self/this` kind of
argument that always goes first)?


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the openssl-project mailing list