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

Possible to use dproto in @safe code. #79

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

puzzlehawk
Copy link

  1. With this changes it should be possible to use structs generated with dproto in @safe functions. However, parsing protobuf code is still not @safe.

  2. Removed deprecated inline imports.

@coveralls
Copy link

coveralls commented Jun 14, 2016

Coverage Status

Coverage decreased (-0.2%) to 74.663% when pulling 5e95d6d on puzzlehawk:safeness into 4e47edb on msoucy:master.

@@ -40,6 +42,8 @@ template TagId(alias T)
template ProtoAccessors()
{

@safe:

Copy link
Contributor

Choose a reason for hiding this comment

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

This shouldn't be applied to the templated methods; you can't guarantee it is appropriate.

I would suggest it only be applied to the non-templated serialize() method. Attribute inference will take care of the rest.

Copy link
Author

Choose a reason for hiding this comment

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

OK. Didn't know about attribute inference :)
But still the templated deserialize() has to be marked as @safe too. Is it appropriate to require that the ProtoInputRange R provides @safe functions? My answer is yes, you should definitively enforce bound checks when parsing data from non-trusted sources.

@WebDrake
Copy link
Contributor

My earlier comment, that @safe should only be applied to non-templated functions and methods, should be taken as applying to the entire commit. It's simply not appropriate to make promises about templated methods where you have no way of knowing if the instantiation will actually be compatible with the @safe attribute.

Apart from that, the commit message should be something meaningful explaining the rationale for the changes.

if(isProtoOutputRange!R &&
(T.msgType == "double".msgType || T.msgType == "float".msgType))
{
r.put(src.nativeToLittleEndian!(BuffType!T)[]);
}

/// Ditto
void writeProto(string T, R)(ref R r, const BuffType!T src)
void writeProto(string T, R)(ref R r, const BuffType!T src) @trusted
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't understand the rationale for making these @trusted. It in any case seems to me unwise in the case of a templated method.

Copy link
Author

Choose a reason for hiding this comment

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

I don't feel that comfortable with @trusted here either. Better would be @safe which would require R.put() to be either safe or trusted. So it would be the users choice.
This could break compatibility to older code.

@WebDrake
Copy link
Contributor

Broadly, I'm concerned that this PR is just trying to get dproto code to compile inside @safe code blocks, without actually thinking through the rationale of what actually is safe.

I speak here purely as a user, not a maintainer, but I would not be happy to see dproto promising @safe code without a better rationale than is given here for the changes made.

@WebDrake
Copy link
Contributor

  1. Removed deprecated inline imports.

I don't see any sign of this in the diff ... ?

@puzzlehawk
Copy link
Author

@WebDrake: Thanks for having a look at this.

Broadly, I'm concerned that this PR is just trying to get dproto code to compile inside @safe code blocks, without actually thinking through the rationale of what actually is safe.

Partially true. For me it seems to be important that processing of non-trusted data cannot lead to memory corruptions. dproto will likely be used in networking where none of the incoming data can be trusted. Therefore I claim providing @safety should be mandatory for that kind of library. Clearly we can argue about user provided code such as output ranges. For instance how to we handle R.put() in writeProto()? Do we require it to be @safe? Could be reasonable. I agree that having writeProto() just @trusted would be dangerously transparent to the user.

  1. Removed deprecated inline imports.

I don't see any sign of this in the diff ... ?

Your eyes are right. Copy-paste accident on my side.

@WebDrake
Copy link
Contributor

For me it seems to be important that processing of non-trusted data cannot lead to memory corruptions.

Yes. This is why it's important to differentiate between code that actually is safe, versus code that merely compiles inside a @safe block. Your changes as they are currently actually make the user less safe, by providing a false promise that the code meets the requirements of @safe.

Therefore I claim providing @safety should be mandatory for that kind of library.

Note that the library's ability to provide genuine guarantees of safety may depend on the way the downstream user is using the library. It isn't necessarily the place of a library author to ban use-cases that are incompatible with @safe code blocks.

For instance how to we handle R.put() in writeProto()? Do we require it to be @safe? Could be reasonable.

You should not be putting @trusted on anything that you cannot manually verify as memory-safe. Given that you don't know what R is, it would be very dangerous to use @trusted in this context. A @safe put() method for the given R is therefore a necessary (but not sufficient) condition in order for the corresponding writeProto() instantiation to be inferred as @safe.

In this case, I think the problem with writeProto() may not only be whether R.put() is safe, but also the cast to ubyte[]. I would suggest looking at how converting a BuffType!T to ubyte[] could be made verifiably safe. Probably the best way would be to replace the cast with a function that takes BuffType!T as input and returns a const(ubyte[]) in a way that is guaranteed safe for the types that the BuffType template evaluates to.

Note that if BuffType!T is a value-type, you may have to deal with the fact that the resulting ubyte[] will be invalid the moment the BuffType!T src variable goes out of scope.

@msoucy msoucy added the ready label Jun 23, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants