-
Notifications
You must be signed in to change notification settings - Fork 29.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
src: improve SSL version extraction logic #23050
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
Commit message also has a typo (SSL) :)
src/node.cc
Outdated
} | ||
} | ||
{ | ||
// sample opnssl version stirng format |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: string
4bc66c8
to
aee216b
Compare
@addaleax - thanks, fixed both. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason not to do the same to the similar block of code in NodeTraceStateObserver::OnTraceEnabled()
?
Lines 239 to 258 in 59a8324
#if HAVE_OPENSSL | |
// Stupid code to slice out the version string. | |
{ // NOLINT(whitespace/braces) | |
size_t i, j, k; | |
int c; | |
for (i = j = 0, k = sizeof(OPENSSL_VERSION_TEXT) - 1; i < k; ++i) { | |
c = OPENSSL_VERSION_TEXT[i]; | |
if ('0' <= c && c <= '9') { | |
for (j = i + 1; j < k; ++j) { | |
c = OPENSSL_VERSION_TEXT[j]; | |
if (c == ' ') | |
break; | |
} | |
break; | |
} | |
} | |
trace_process->SetString("openssl", | |
std::string(&OPENSSL_VERSION_TEXT[i], j - i)); | |
} | |
#endif |
src/node.cc
Outdated
} | ||
} | ||
{ | ||
// sample opnssl version string format |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
openssl
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks @richardlau - made both the changes. Didn't know there were same patterns elsewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did point it out in #22712 (comment) but given the number of comments in that PR it's easily overlooked/forgotten.
src/node.cc
Outdated
{ | ||
// sample openssl version string format | ||
// for reference: "OpenSSL 1.1.0i 14 Aug 2018" | ||
std::string ssl(OPENSSL_VERSION_TEXT); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you wrap the first 5 lines into a constexpr string()(const char*)
function, and reuse in the second place?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@refack - sure, given OPENSSL_VERSION_TEXT
is accessible everywhere (in the caller and the callee) do you mind if I don't pass it? are there any guidance on that? thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, of course, but I gave it a try, and we might need C++17 for this to work as expected.
But is could definatly be inline
src/node.cc
Outdated
size_t first = ssl.find(" "); | ||
size_t second = ssl.find(" ", first + 1); | ||
CHECK_GT(second, first); | ||
ssl = ssl.substr(first + 1, second - first - 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please declare a new variable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, but why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are reusing a variable for no good reason. substr
will do a copy anyway.
c47e24a
to
92e96bc
Compare
@refack - pushed changes as you suggested, please have a look. thanks. |
src/node.h
Outdated
@@ -487,7 +487,7 @@ NODE_DEPRECATED("Use WinapiErrnoException(isolate, ...)", | |||
#endif | |||
|
|||
const char* signo_string(int errorno); | |||
|
|||
const std::string GetOpenSSLVersion(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather not declare this as a public API.
IMHO no declaration is required, just put in higher in node.cc
, but if you feel a decl is required, I think I agree util.h
node_crypto.h
is a better place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is split out into a separate function, it should be defined in node_crypto.h
, as is all other OpenSSL-specific code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could be useful in the node-report PR, especially if we go down the JSON format route (where I think this sliced version string is more appropriate than the full string currently used). But declaring the function (in node_crypto.h
) could easily be done over in that PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@richardlau Regarding the node-report PR … it still wouldn’t have to be public API, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding the node-report PR … it still wouldn’t have to be public API, right?
Correct. It doesn't need to be declared at all in this PR (as it's only used in src/node.cc
). For use in the node-report PR it should be declared as a node internal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
followed the suggestions; moved things to node-crypto
.
to be clear: what is a public API
in this context? symbols accessible outside of node.exe
? methods visible and callable when node is a shared library? AFAIK visibility of symbols in object files are platform dependent, and are managed (for embedders) manually at the moment? In the absence of that, every method is visible in say Linux? or is it that we follow a convention that all declared methods in node.h
is deemed public
? please let me know. thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is a
public API
in this context
Methods in headers that are included in the header tarball and not guarded by NODE_WANT_INTERNALS
, i.e.:
#include <node.h>
#include <node_api.h>
#include <node_buffer.h>
#include <node_version.h>
#include <node_object_wrap.h>
src/node.cc
Outdated
size_t second = ssl.find(" ", first + 1); | ||
CHECK_GT(second, first); | ||
std::string result = ssl.substr(first + 1, second - first - 1); | ||
return result; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can just return ssl.substr(…);
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 since in C++14 it's not guaranteed to elide
d704536
to
915f478
Compare
src/node_crypto.cc
Outdated
size_t first = ssl.find(" "); | ||
size_t second = ssl.find(" ", first + 1); | ||
CHECK_GT(second, first); | ||
std::string result = ssl.substr(first + 1, second - first - 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Can we simply return the result of substr
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@thefourtheye - please see
#23050 (comment) @refack 's response to the same: looks like that may break in c++14 world. I don't know it myself, so following SME opinion. Hope you are good with that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like @refack is actually okay with that suggestion, can you please confirm @refack? According to https://en.wikipedia.org/wiki/Copy_elision#Summary,
an implementation may omit a copy operation resulting from a return statement, even if the copy constructor has side effects.
So, there is no guarantee that a copy will be made and we should still be fine here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gireeshpunathil @thefourtheye I think @refack’s comment was agreeing that this might otherwise not elide if we don’t return the result directly. And it’s unavoidable to create a new string object here, since substr()
already does that.
But either way: This is not performance-critical code. Just go with the simplest form. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, reduced to the simplest form.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohh yes please. Copy elision is a good thing that we may get for free in C++17, but for now we need to be more explicit.
src/node_crypto.h
Outdated
@@ -98,6 +98,7 @@ extern int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx); | |||
extern void UseExtraCaCerts(const std::string& file); | |||
|
|||
void InitCryptoOnce(); | |||
const std::string GetOpenSSLVersion(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Btw, const
on return types is ignored and at least some versions of GCC provide compiler warnings for that… might be best to just omit it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, removed it.
49e42d1
to
315dda0
Compare
Commit message has a typo: |
The openssl version as defined in ssl libraries is complex. The current logic to extract the major.minor.patch format uses C semantics to loop through the text and search for specific patterns. Use C++ string to tidy it up.
315dda0
to
aa8470e
Compare
@richardlau - thanks, fixed. |
@gireeshpunathil thank you for following up on all the twists and turns 💟 |
A different approach would be to compute it from #ifdef OPENSSL_FIPS
static const char fips[] = "-fips";
#else
static const char fips[] = "";
#endif
char s[32];
uint8_t major = OPENSSL_VERSION_NUMBER >> 28;
uint8_t minor = OPENSSL_VERSION_NUMBER >> 20;
uint8_t fix = OPENSSL_VERSION_NUMBER >> 12;
uint8_t patch = (OPENSSL_VERSION_NUMBER & 240) - 39; // 'a', 'b', etc.
snprintf(s, sizeof(s), "%d.%d.%d%c%s", major, minor, fix, patch, fips); I'm reasonably sure most compilers will be able to optimize that to a constant expression. |
@bnoordhuis - thanks for the suggestion 0x4005cd <main>: push rbp
0x4005ce <main+1>: mov rbp,rsp
=> 0x4005d1 <main+4>: sub rsp,0x40
0x4005d5 <main+8>: mov BYTE PTR [rbp-0x1],0x1 // '1'
0x4005d9 <main+12>: mov BYTE PTR [rbp-0x2],0x1 // '1'
0x4005dd <main+16>: mov BYTE PTR [rbp-0x3],0x0 // '0'
0x4005e1 <main+20>: mov BYTE PTR [rbp-0x4],0x69 // 'i'
0x4005e5 <main+24>: movsx ecx,BYTE PTR [rbp-0x4]
0x4005e9 <main+28>: movsx edi,BYTE PTR [rbp-0x3]
0x4005ed <main+32>: movsx esi,BYTE PTR [rbp-0x2]
0x4005f1 <main+36>: movsx edx,BYTE PTR [rbp-0x1]
0x4005f5 <main+40>: lea rax,[rbp-0x30]
0x4005f9 <main+44>: mov QWORD PTR [rsp+0x8],0x4006f1
0x400602 <main+53>: mov DWORD PTR [rsp],ecx
0x400605 <main+56>: mov r9d,edi
0x400608 <main+59>: mov r8d,esi
0x40060b <main+62>: mov ecx,edx
0x40060d <main+64>: mov edx,0x4006e0
0x400612 <main+69>: mov esi,0x20
0x400617 <main+74>: mov rdi,rax
0x40061a <main+77>: mov eax,0x0
0x40061f <main+82>: call 0x4004a0 <snprintf@plt> the token values are pre-computed by the compiler! so the runtime effort is only for formatting. C++ dump shows expensive calls, not comparable. So now it is a question on performance vs. readability. Do you insist on high-performant code here? I think this sequence will be invoked exactly twice in the lifecycle of the process. Please let me know. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
I see similar outputs from gcc and clang 🤷♂️ https://godbolt.org/z/dKLS8v |
@gireeshpunathil Interesting. At one time gcc was able to replace constant snprintf() calls (really Here is an alternative take that does result in a constant expression at #include <stdio.h>
#define OPENSSL_VERSION_TEXT "OpenSSL 1.1.0i 14 Aug 2018"
constexpr int search(const char* s, int n, int c) {
return *s == c ? n : search(s + 1, n + 1, c);
}
int main() {
const int start = search(OPENSSL_VERSION_TEXT, 0, ' ') + 1;
const int end = search(OPENSSL_VERSION_TEXT, start, ' ') - 1;
const int len = end - start;
printf("%.*s\n", len, &OPENSSL_VERSION_TEXT[start]);
} Output: 00000000004004f8 <main>:
4004f8: 50 push %rax
4004f9: bf c0 05 40 00 mov $0x4005c0,%edi
4004fe: be 06 00 00 00 mov $0x6,%esi
400503: ba ac 05 40 00 mov $0x4005ac,%edx
400508: 31 c0 xor %eax,%eax
40050a: e8 f1 fe ff ff callq 400400 <printf@plt>
40050f: 31 c0 xor %eax,%eax
400511: 59 pop %rcx
400512: c3 retq
That's true, but it happens at start-up. On slow systems (think Raspberry Pis and such) Node's start-up times are not great so we should try within reason to shave off cycles where we can. |
thaanks @bnoordhuis, pushed a new change based on your suggestion, and added you as a co-author. Few points:
- const int end = search(OPENSSL_VERSION_TEXT, start, ' ') - 1;
+ const int end = search(OPENSSL_VERSION_TEXT + start, start, ' ') + 1;
|
// for reference: "OpenSSL 1.1.0i 14 Aug 2018" | ||
char buf[128]; | ||
const int start = search(OPENSSL_VERSION_TEXT, 0, ' ') + 1; | ||
const int end = search(OPENSSL_VERSION_TEXT + start, start, ' ') + 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I posted a mildly incorrect version of search()
(even though it looks like it worked out okay; amazing, computers usually aren't that forgiving.)
It should look like this:
constexpr int search(const char* s, int n, int c) {
return s[n] == c ? n : search(s, n + 1, c); // note: s isn't incremented
}
And the search for end
should therefore be this:
const int end = search(OPENSSL_VERSION_TEXT, start, ' ') - 1; // note: -1 to exclude the blank
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you meant:
const int end = search(ssl, start, ' ') + 1;
instead of:
const int end = search(ssl, start, ' ') - 1;
?
else I get truncated output: for example when expecting 1.1.0i-fips
I get 1.1.0i-fi
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about this:
constexpr int SSLVersion_Helper2(const int s) {
return OPENSSL_VERSION_TEXT[s + 7] == ' ' ? s + 7 : s + 12;
}
constexpr const int SSLVersion_Helper()
{
// option 1 "OpenSSL 1.1.0i 14 Aug 2018"
// option 2 "OpenSSL 1.1.0i-fips 14 Aug 2018"
// 7 = strlen("OpenSSL");
static_assert(OPENSSL_VERSION_TEXT[7] == ' ',
OPENSSL_VERSION_TEXT " + 7 isn't a ' ' char");
// 7 = strlen("OpenSSL 1.1.0i");
// 12 = strlen("OpenSSL 1.1.0i-fips");
static_assert(OPENSSL_VERSION_TEXT[SSLVersion_Helper2(7)] == ' ',
OPENSSL_VERSION_TEXT " + 14 or 19 isn't a ' ' char");
return SSLVersion_Helper2(7);
}
const std::string kSSLVersionString{OPENSSL_VERSION_TEXT + 7,
OPENSSL_VERSION_TEXT + SSLVersion_Helper()};
As K.I.S.S. as I could while it still compiles on GCC4.9
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks @refack . I am seeing it as compiled into a regular function, with no static awareness of the const string
or const int
passed to it and leveraged by the compiler. Is it only my gcc? can you please check?
(gdb) x/16i SSLVersion_Helper2
0x400eb8 <_Z18SSLVersion_Helper2i>: push rbp
0x400eb9 <_Z18SSLVersion_Helper2i+1>: mov rbp,rsp
0x400ebc <_Z18SSLVersion_Helper2i+4>: mov DWORD PTR [rbp-0x4],edi
0x400ebf <_Z18SSLVersion_Helper2i+7>: mov eax,DWORD PTR [rbp-0x4]
0x400ec2 <_Z18SSLVersion_Helper2i+10>: add eax,0x7
0x400ec5 <_Z18SSLVersion_Helper2i+13>: cdqe
0x400ec7 <_Z18SSLVersion_Helper2i+15>: movzx eax,BYTE PTR [rax+0x401228]
0x400ece <_Z18SSLVersion_Helper2i+22>: cmp al,0x20
0x400ed0 <_Z18SSLVersion_Helper2i+24>: jne 0x400eda <_Z18SSLVersion_Helper2i+34>
0x400ed2 <_Z18SSLVersion_Helper2i+26>: mov eax,DWORD PTR [rbp-0x4]
0x400ed5 <_Z18SSLVersion_Helper2i+29>: add eax,0x7
0x400ed8 <_Z18SSLVersion_Helper2i+32>: jmp 0x400ee0 <_Z18SSLVersion_Helper2i+40>
0x400eda <_Z18SSLVersion_Helper2i+34>: mov eax,DWORD PTR [rbp-0x4]
0x400edd <_Z18SSLVersion_Helper2i+37>: add eax,0xc
0x400ee0 <_Z18SSLVersion_Helper2i+40>: pop rbp
0x400ee1 <_Z18SSLVersion_Helper2i+41>: ret
(gdb)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in other words, where do we see the benefit of the constexpr
optimizations that was the theme of this PR for sometime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
more for the academics: https://godbolt.org/z/qWyDbk show it being compile time only (with -O2
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still LGTM
Landed in d3d6cd3 |
The openssl version as defined in ssl libraries is complex. The current logic to extract the major.minor.patch format uses C semantics to loop through the text and search for specific patterns. Use C++ string to tidy it up. PR-URL: #23050 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Richard Lau <[email protected]> Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Sakthipriyan Vairamani <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
const int start = search(OPENSSL_VERSION_TEXT, 0, ' ') + 1; | ||
const int end = search(OPENSSL_VERSION_TEXT + start, start, ' ') + 1; | ||
const int len = end - start; | ||
snprintf(buf, len, "%.*s\n", len, &OPENSSL_VERSION_TEXT[start]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The second arg should have been sizeof(buf)
, not len
. I'll open a pull request. (edit: #23622)
The openssl version as defined in ssl libraries is complex. The current logic to extract the major.minor.patch format uses C semantics to loop through the text and search for specific patterns. Use C++ string to tidy it up. PR-URL: #23050 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Richard Lau <[email protected]> Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Sakthipriyan Vairamani <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
The openssl version as defined in ssl libraries is complex. The current logic to extract the major.minor.patch format uses C semantics to loop through the text and search for specific patterns. Use C++ string to tidy it up. PR-URL: #23050 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Richard Lau <[email protected]> Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Sakthipriyan Vairamani <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
The openssl version as defined in ssl libraries is complex. The current logic to extract the major.minor.patch format uses C semantics to loop through the text and search for specific patterns. Use C++ string to tidy it up. PR-URL: #23050 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Richard Lau <[email protected]> Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Sakthipriyan Vairamani <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
The openssl version as defined in ssl libraries is complex. The current logic to extract the major.minor.patch format uses C semantics to loop through the text and search for specific patterns. Use C++ string to tidy it up. PR-URL: #23050 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Richard Lau <[email protected]> Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Sakthipriyan Vairamani <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
The openssl version as defined in ssl libraries is complex. The current logic to extract the major.minor.patch format uses C semantics to loop through the text and search for specific patterns. Use C++ string to tidy it up. PR-URL: #23050 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Richard Lau <[email protected]> Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Sakthipriyan Vairamani <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
The openssl version as defined in ssl libraries is complex. The current logic to extract the major.minor.patch format uses C semantics to loop through the text and search for specific patterns. Use C++ string to tidy it up. PR-URL: #23050 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Richard Lau <[email protected]> Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Sakthipriyan Vairamani <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
The openssl version as defined in ssl libraries is complex. The current logic to extract the major.minor.pacth format uses C semantics to loop through the text and search for specific patterns. Use C++ string to tidy it up.
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes