Skip to content
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

Property implementation #8224

Closed
wants to merge 2 commits into from
Closed

Property implementation #8224

wants to merge 2 commits into from

Conversation

paulidale
Copy link
Contributor

@paulidale paulidale commented Feb 13, 2019

A first pass at implementing some efficient property definition and query infrastructure.

Properties are defined by providers as strings which are parsed into name, value pairs.
Queries are parsed into name relation value triplets.
Implementations that match the query are considered for further use whereas implementations that don't match are immediately discarded from consideration.

The property system, allows global properties to be specified in addition to local properties (which can override globals).

If there is a match, there are capabilities for caching the outcome which will improve performance in the future.

The implementation database permits several interfaces to operate within:

  1. add,
  2. remove,
  3. fetch,
  4. cache_get,
  5. cache_set and
  6. set_global_properties

The generate usage pattern is:

if (cache_get(...) != NULL)
    return cache_got;

if ((result = fetch(...)) == NULL)
    return NULL;
cache_set(nid, properties, result)
  • tests are added or updated

@paulidale paulidale added branch: master Merge to master branch FIPS labels Feb 13, 2019
@levitte levitte added this to In progress in 3.0 New Core + FIPS via automation Feb 13, 2019
@levitte
Copy link
Member

levitte commented Feb 13, 2019

I added this PR to the newly created github project "3.0 New Core + FIPS"

Also, you need to rebase.

Copy link
Member

@levitte levitte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, would you mind adding internal documentation for the functions declared in include/internal/property.h, i.e. a manpage in doc/internal/man3?

crypto/property/defn_cache.c Outdated Show resolved Hide resolved
3.0 New Core + FIPS automation moved this from In progress to Needs review Feb 13, 2019
@levitte levitte removed the FIPS label Feb 13, 2019
@levitte
Copy link
Member

levitte commented Feb 13, 2019

I removed the FIPS label, as this isn't the FIPS module per se. I believe adding this to the "3.0 New Core + FIPS" is a better way to mark these sorts of PRs

typedef struct {
const char *prop;
PROPERTY_LIST *defn;
char body[1];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"unwarranted chumminess with the compiler" (web-search it)
Pay the price of portable code and make this a pointer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Double allocating and ruining cache coherency in code that's meant to be fast to avoid something that's always worked...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's a misguided/premature optimization, at the expense of more clear code. We're going to be dispatching to crypto code :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C99 allows using char body[]; Is C99 viable target for OpenSSL 3.0.0?

Copy link
Contributor Author

@paulidale paulidale Feb 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't use C99. However, this code is portable and safe. There are two restrictions: don't use an array of such structures (no space to use between records) and don't store a type other than char there (alignment).

( ',' ( '-'? PropertyName | PropertyName ( '=' | '!=' ) Value ) )*
Value ::= NumberLiteral
| StringLiteral
StringLiteral ::= QuotedString | UnquotedString
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think unquotedstring is a very big mistake. It makes it really hard to add keywords to the query language in the future. Look at perl's "barewords" evolution, for example.

Value ::= NumberLiteral
| StringLiteral
StringLiteral ::= QuotedString | UnquotedString
QuotedString ::= '"' [^"]* '"'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should allow backslash-escape inside the quoted string.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? so we can write fips="Y\e\s" ?

I'd be happy to ban \ inside a string to provide a capability to add it painlessly in the future.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Banning it for future expansion helps. But I meant to only escape quotes, as in things like "Hello "world""

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If anyone is ever going to want to have a Windows path in a quoted string, we'd better not use \ as the escape character.

That being said, the \ is more or less universally known as an escape character, and is already used as such elsewhere in OpenSSL, so it's actually a little surprising to have something different for property values.

(and I'm curious, where was ^ inspired from? That's actually used in VMS file specs, where you'll see things like openssl-1^.0^.2q^.tar.gz, but I've not seen you as VMS savvy, so...)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where was ^ inspired from?

The caret at the beginning of a character class inverts the set, i.e. [^a-b] is the complement of [a-b]. If you want to include a literal caret, it must not be first in the set. See GREP(1).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Of course you know that, it's part of your Perl-fu. It was just too early in the morning... ;-) ).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

D'oh.

And still, that was after the first coffee.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the ^ is stretching eBNF a little.

crypto/property/README Outdated Show resolved Hide resolved
crypto/property/README Outdated Show resolved Hide resolved
crypto/property/defn_cache.c Show resolved Hide resolved
crypto/property/defn_cache.c Outdated Show resolved Hide resolved
crypto/property/defn_cache.c Outdated Show resolved Hide resolved
include/openssl/lhash.h Show resolved Hide resolved
test/property_test.c Outdated Show resolved Hide resolved
names and values to small integer indices. Names and values are
stored in separate hash tables. The two Boolean values "yes" and "no"
are populated as the first two members of the value table. The string
"name" is automatically populated as the first property name, to enable
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does this happen? I couldn't see it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See ossl_property_parse_init in property_parse.c.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That function only seems to define "provider", "version", "fips" and "engine", but not "name"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The question is which names are we going to reserve?

I changed "name" to "provider" since it seemed more applicable but missed the README.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix is to not say which property names are pre-loaded, just to say that they are.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can have the discussion about which get added later. I expect some worthwhile ones will naturally appear over the course of the project.

test/property_test.c Outdated Show resolved Hide resolved
test/property_test.c Outdated Show resolved Hide resolved
* space and time efficient algorithms if this becomes a bottleneck.
*/

typedef struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unnamed struct isn't common. also same bad chumminess thing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnamed struct might be uncommon, but naming it becomes a bit silly if that name is never used. I see no reason to add a struct name now.

crypto/property/defn_cache.c Show resolved Hide resolved
include/internal/property.h Outdated Show resolved Hide resolved
include/internal/property.h Outdated Show resolved Hide resolved
include/internal/property.h Outdated Show resolved Hide resolved
include/internal/property.h Outdated Show resolved Hide resolved
include/internal/property.h Outdated Show resolved Hide resolved
include/internal/property.h Outdated Show resolved Hide resolved
include/internal/property.h Outdated Show resolved Hide resolved
@levitte
Copy link
Member

levitte commented Feb 13, 2019

Looking through the code again and its intended use, I'm unsure that the functions declared in include/internal/property.h are named right.

That store (or those stores) are going to be used to save away methods, i.e. instances of EVP_CIPHER, EVP_MD, etc. Do we call them implementations or do we call them methods? Historically, they were called the latter (it's even more visible if you consider EVP_PKEY_METHOD), so I wonder of ossl_method_ isn't a better function prefix than ossl_impl_.

Food for thought.

include/internal/property.h Outdated Show resolved Hide resolved
test/build.info Outdated Show resolved Hide resolved

ossl_impl_store_cleanup();
return 0;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make sure that this is called automatically, either as part of the init process, or in here with the help of a RUN_ONCE function (see #8225 to see how I do that)

ossl_prop_defn_cleanup();
ossl_impl_store_free(g_implementations);
g_implementations = NULL;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make sure that this is called automatically, either as part of the cleanup process, or in here with the help of OPENSSL_atexit() (see #8225 to see how I do that)

crypto/property/property.c Show resolved Hide resolved
@paulidale paulidale force-pushed the property branch 2 times, most recently from 82ed864 to 88c0401 Compare February 14, 2019 01:50
@paulidale
Copy link
Contributor Author

paulidale commented Feb 14, 2019

I've addressed most of the comments (resolving those that I did fix). This mostly leaves the library context (& g_implementations) some parsing questions and the run once.

@paulidale
Copy link
Contributor Author

paulidale commented Feb 14, 2019

Looking through the code again and its intended use, I'm unsure that the functions declared in include/internal/property.h are named right.

Let's settle this before I do the documentation.

Settled.

@paulidale paulidale changed the title Property implementation WIP: Property implementation Feb 14, 2019
@paulidale
Copy link
Contributor Author

paulidale commented Feb 14, 2019

Travis failures look to be overly aggressive detection of unused macro generated functions. Do we have a standard way of prevent these without exposing the structures via a header file?

Fixed in a different PR.

crypto/property/README Outdated Show resolved Hide resolved
crypto/property/README Outdated Show resolved Hide resolved
@paulidale
Copy link
Contributor Author

Tests are updated so that they don't reinitialise the properties anymore.
I think that's everything once the CIs pass.

@paulidale
Copy link
Contributor Author

The CIs pass :)

Copy link
Member

@t-j-h t-j-h left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't think we should have bare PROPERTY and it should have an OSSL or OPENSSL prefix.

@paulidale
Copy link
Contributor Author

paulidale commented Feb 16, 2019

Which PROPERTY ? Everything exposed outside of the crypto/property directory starts OSSL_ doesn't it? All functions exposed from crpyto/property also start ossl_. Some of the types don't, are they realistically a problem?

@t-j-h
Copy link
Member

t-j-h commented Feb 16, 2019

You have ossl_ prefixes on the functions expected to be used outside of the property directory but no prefix on the typedefs. They should be OSSL_ ... basically we don't want to run into clashes with other code and PS_IDX and PROPERTY are likely to clash.

Yes I know these aren't currently expected to be visible elsewhere - but they may evolve that way - and we should be clean in our "namespace" usage IMHO.

@paulidale
Copy link
Contributor Author

I've prefixed the internal symbols.

Copy link
Member

@t-j-h t-j-h left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once the CIs show clear for the most recent change - approved.

@paulidale
Copy link
Contributor Author

@levitte @mattcaswell I'll merge this in the morning (my time) unless there are objections.

@paulidale
Copy link
Contributor Author

Squashed...

@mattcaswell mattcaswell added the approval: done This pull request has the required number of approvals label Feb 17, 2019
@levitte
Copy link
Member

levitte commented Feb 17, 2019

I'd like to run a test tomorrow against things I have that build on this...

@levitte
Copy link
Member

levitte commented Feb 17, 2019

(It looked good visually, though...)

@paulidale
Copy link
Contributor Author

Let me know when you're done and I'll merge it or merge it yourself if the time-zones are immiscible.

Properties are a sequence of comma separated name=value pairs.  A name
without a corresponding value is assumed to be a Boolean and have the
true value 'yes'.  Values are either strings or numbers.  Strings can be
quoted either _"_ or _'_ or unquoted (with restrictions).  There are no
escape characters inside strings.  Number are either decimal digits or
'0x' followed by hexidecimal digits.  Numbers are represented internally
as signed sixty four bit values.

Queries on properties are a sequence comma separated conditional tests.
These take the form of name=value (equality test), name!=value (inequality
test) or name (Boolean test for truth).  Queries can be parsed, compared
against a definition or merged pairwise.
levitte pushed a commit that referenced this pull request Feb 18, 2019
Properties are a sequence of comma separated name=value pairs.  A name
without a corresponding value is assumed to be a Boolean and have the
true value 'yes'.  Values are either strings or numbers.  Strings can be
quoted either _"_ or _'_ or unquoted (with restrictions).  There are no
escape characters inside strings.  Number are either decimal digits or
'0x' followed by hexidecimal digits.  Numbers are represented internally
as signed sixty four bit values.

Queries on properties are a sequence comma separated conditional tests.
These take the form of name=value (equality test), name!=value (inequality
test) or name (Boolean test for truth).  Queries can be parsed, compared
against a definition or merged pairwise.

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from #8224)
levitte pushed a commit that referenced this pull request Feb 18, 2019
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from #8224)
@paulidale
Copy link
Contributor Author

Merged, thanks for the extensive and positive feedback.

@paulidale paulidale closed this Feb 18, 2019
3.0 New Core + FIPS automation moved this from Needs review to Done Feb 18, 2019
@paulidale paulidale deleted the property branch February 18, 2019 06:35
@levitte
Copy link
Member

levitte commented Feb 18, 2019

... someone's in a rush. 😉

My tests ran well after some appropriate mods. The manual bits need some fixups, something I discovered moments ago...

@paulidale
Copy link
Contributor Author

paulidale commented Feb 18, 2019 via email

@levitte
Copy link
Member

levitte commented Feb 18, 2019

Care to look at #8265?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approval: done This pull request has the required number of approvals branch: master Merge to master branch
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

None yet

9 participants