Implement ERR_raise() / ERR_raise_data()#9452
Implement ERR_raise() / ERR_raise_data()#9452levitte wants to merge 10 commits intoopenssl:masterfrom
Conversation
|
One commit mentions the following little program #include <stdio.h>
void first(void)
{
printf("Hello! ");
}
void foo(const char *bar)
{
printf("%s", bar);
}
int main()
{
/* This */
(first(),foo)("cookie");
}It shows the trick used to implement |
|
Dropping ERR_put_error() is an API break. |
Ah, I did not notice that it is now implemented as macro. OK then. |
richsalz
left a comment
There was a problem hiding this comment.
So this makes #9441 needless? Or do folks still want the unused argument removed?
I am concerned that this could add variable timing to errors and therefore be a timing oracle. I'd be delighted to be convinced that's needless, can you do that?
Depends... do people still want to use the
Only if you have additional data, which is a problem we already have with |
|
Regarding the timing oracle and additional error data... we do have a problem here, 'cause our error message are quite terse and non-descript at times, so there's a desire to add additional data, but the clumsiness of |
|
If this gets merged, then I will look at changing the script in #9441 to rewrite things in terms of |
|
This looks like a good approach. |
crypto/err/err_locl.h
Outdated
There was a problem hiding this comment.
these are not time-critical, just make them internal functions. Then you don't have to worry about parenthesizing or someone calling err_clear_data(p, i++)
There was a problem hiding this comment.
err_allocate is a misleading name since it doesn't actually allocate anything.
There was a problem hiding this comment.
But it does allocate a new error record slot. Sure, it's in a ring buffer, but still. Allocation as a term covers more than merely allocating memory on the heap, doesn't it? I'm pretty sure I have seen that word used more broadly.
However, feel free to suggest a name that you find more suitable.
There was a problem hiding this comment.
Is the name changing for this one?
I tend to agree that (internal) functions might be a nicer choice.
|
I've a question... Right now, this PR implements ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE, NULL);Is that dangling NULL ok, or will people find that jarring? Should I then implement two variants, ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);and this for the more complex report: ERR_raise_data(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE, "name=%s", name); |
|
I'd vote for the cleanliness approach with two functions. At least in case we expect to have many calls that do not need to supply any additional data - and I suppose it would be so because currently almost all the calls do not supply it. |
|
Sorry for brevity, can't browse the PR. I'd prefer to have not an integer library code but a string one. |
|
@beldmit, there are associated strings with the library codes, and for those who want to quickly check what library an error came from, having to strcmp is a bit overkill... (plus, that would be a fairly serious API break) |
|
@t8m, that's what I was thinking. So ok, I'll make that change. |
|
We've got a fast string to small integer map, so converting from a string library name to an integer one wouldn't be a major imposition (plus these are errors which should be uncommon). I agree with @beldmit that it would be nicer. Doing the same for the reason would be trickier (typos) but it would sidestep the one vs two API question. I'd love to see: |
That will still require that the caller does something more than just compare |
|
In other words, I believe that the library and reason as strings is for some OpenSSL > 3.0. |
|
Meanwhile, the CIs are finally happy |
paulidale
left a comment
There was a problem hiding this comment.
If the name isn't changing and the macros aren't refactored into functions....
crypto/err/err_locl.h
Outdated
There was a problem hiding this comment.
Is the name changing for this one?
I tend to agree that (internal) functions might be a nicer choice.
To deallocate the err_data field and then allocating it again might be a waste of processing, but may also be a source of errors when memory is scarce. While we normally tolerate that, the ERR sub-system is an exception and we need to pay closer attention to how we handle memory. This adds a new err_data flag, ERR_TXT_IGNORE, which means that even if there is err_data memory allocated, its contents should be ignored. Deallocation of the err_data field is much more selective, aand should only happen when ERR_free_state() is called. Fixes openssl#9458 Reviewed-by: Paul Dale <[email protected]> (Merged from openssl#9459)
Considering other ERR branches just went in, I need to rebase and refactor a little bit anyway, so... |
|
I'll wait for the new version. |
New header file, include/openssl/macros.h, which contains diverse useful macros that we use elsewhere. We also add the new macro OPENSSL_FUNC, which is an alias for __FUNC__, __FUNCTION__, __FUNCSIG or __func__, depending on what the compiler supports. In the worst case, it's an alias for the string "(unknown function)".
The useful inner macros are now static inline functions. That will make them easier to debug in the future.
The new building block are ERR_new(), ERR_set_debug(), ERR_set_error(), ERR_vset_error(), which allocate a new error record and set the diverse data in them. They are designed in such a way that it's reasonably easy to create macros that use all of them but then rely completely on the function signature of ERR_set_error() or ERR_vset_error().
This macro uses a trick in C. The following is permitted:
#include <stdio.h>
void first(void)
{
printf("Hello! ");
}
void foo(const char *bar)
{
printf("%s", bar);
}
int main()
{
/* This */
(first(),foo)("cookie");
}
ERR_raise() can be used to implement FUNCerr() as well, which takes
away the need for the special function ERR_put_func_error().
squash! ERR: Implement the macro ERR_raise() and use it
Make sure to mention ERR_raise_data() too
… macro Also, deprecate ERR_put_error()
The core now supplies its own versions of ERR_new(), ERR_set_debug() and ERR_vset_error(). This should suffice for a provider to have any OpenSSL compatible functionlity it desires. The main difference between the ERR functions and the core counterparts is that the core counterparts take an OSSL_PROVIDER parameter instead of the library number. That way, providers do not need to know what number they have been assigned, that information stays in the core.
If compiled with 'no-deprecated', ERR_put_error() is undefined. We had one spot where we were using it directly, because the file and line information was passed from elsewhere. Fortunately, it's possible to use ERR_raise() for that situation, and call ERR_set_debug() immediately after and thereby override the information that ERR_raise() stored in the error record. squash! Avoid using ERR_put_error() directly in OpenSSL code util/mkerr.pl needed a small adjustment to not generate code that won't compile in a 'no-deprecated' configuration.
|
If you want two functions, make the "shorter" one a macro: |
Isn't that exactly what I've done? |
|
Oh yes, you did that, sorry. I was reading the comment threads to see what I’d have to do for #9441.
|
|
Merged. e039ca3 Move some macros from include/openssl/opensslconf.h.in, add OPENSSL_FUNC |
New header file, include/openssl/macros.h, which contains diverse useful macros that we use elsewhere. We also add the new macro OPENSSL_FUNC, which is an alias for __FUNC__, __FUNCTION__, __FUNCSIG or __func__, depending on what the compiler supports. In the worst case, it's an alias for the string "(unknown function)". Reviewed-by: Paul Dale <[email protected]> (Merged from #9452)
The useful inner macros are now static inline functions. That will make them easier to debug in the future. Reviewed-by: Paul Dale <[email protected]> (Merged from #9452)
The new building block are ERR_new(), ERR_set_debug(), ERR_set_error(), ERR_vset_error(), which allocate a new error record and set the diverse data in them. They are designed in such a way that it's reasonably easy to create macros that use all of them but then rely completely on the function signature of ERR_set_error() or ERR_vset_error(). Reviewed-by: Paul Dale <[email protected]> (Merged from #9452)
The ERR_raise() macro uses a trick in C. The following is permitted:
#include <stdio.h>
void first(void)
{
printf("Hello! ");
}
void foo(const char *bar)
{
printf("%s", bar);
}
int main()
{
/* This */
(first(),foo)("cookie");
}
ERR_raise_data() can be used to implement FUNCerr() as well, which
takes away the need for the special function ERR_put_func_error().
Reviewed-by: Paul Dale <[email protected]>
(Merged from #9452)
… macro Also, deprecate ERR_put_error() Reviewed-by: Paul Dale <[email protected]> (Merged from #9452)
The core now supplies its own versions of ERR_new(), ERR_set_debug() and ERR_vset_error(). This should suffice for a provider to have any OpenSSL compatible functionlity it desires. The main difference between the ERR functions and the core counterparts is that the core counterparts take an OSSL_PROVIDER parameter instead of the library number. That way, providers do not need to know what number they have been assigned, that information stays in the core. Reviewed-by: Paul Dale <[email protected]> (Merged from #9452)
Reviewed-by: Paul Dale <[email protected]> (Merged from #9452)
If compiled with 'no-deprecated', ERR_put_error() is undefined. We had one spot where we were using it directly, because the file and line information was passed from elsewhere. Fortunately, it's possible to use ERR_raise() for that situation, and call ERR_set_debug() immediately after and thereby override the information that ERR_raise() stored in the error record. util/mkerr.pl needed a small adjustment to not generate code that won't compile in a 'no-deprecated' configuration. Reviewed-by: Paul Dale <[email protected]> (Merged from #9452)
ERR_raise()andERR_raise_datais new functionality to raise errors, with this intended signature:The intention with this is to have functionality that makes it easier to report errors with additional text, instead of the sometimes cumbersome error handling with
ERR_set_error_data().ERR_raise()andERR_raise_dataare implemented as macros which works with a few building blocks:ERR_new()which simply allocates a new error record in the error queue.ERR_set_debug()which sets debugging information in the current error record. "debugging information" are__FILE__,__LINE__and__func__or variants thereof (in reality, we useOPENSSL_FILE,OPENSSL_LINEandOPENSSL_FUNC, which are defined appropriately for the toolchain that builds this)ERR_set_error()which sets the basic error information in the current error record; library number, reason code, and a format string followed by arguments that form the additional data.All the
FOOerrmacros are reimplemented in terms ofERR_raise()/ERR_raise_data, includingFUNCerr, which also means thatERR_put_func_error()lost its meaning.This functionality was briefly discussed in this thread on openssl-project