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

Validate arguments passed into cadence programs #724

Merged
merged 15 commits into from
Apr 8, 2021

Conversation

SupunS
Copy link
Member

@SupunS SupunS commented Mar 23, 2021

Closes #689

Description

This PR adds validation for the arguments passed into a cadence program, which checks the value against the dynamic type of the value.


For contributor use:

  • Targeted PR against master branch
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work
  • Code follows the standards mentioned here
  • Updated relevant documentation
  • Re-reviewed Files changed in the Github PR explorer
  • Added appropriate labels

@SupunS SupunS requested a review from turbolent March 23, 2021 05:15
@SupunS SupunS self-assigned this Mar 23, 2021
@SupunS SupunS force-pushed the supun/improve-import-export-3 branch 2 times, most recently from 5c59bea to ee7ded2 Compare March 23, 2021 05:27
@SupunS SupunS force-pushed the supun/improve-import-export-3 branch from ee7ded2 to 037b0b0 Compare March 23, 2021 06:13
@SupunS SupunS added the Feature label Mar 29, 2021
Copy link
Member

@turbolent turbolent left a comment

Choose a reason for hiding this comment

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

This is great @SupunS, thank you for noticing this and implementing this all! 👏

@@ -378,7 +379,7 @@ func importValue(value cadence.Value) interpreter.Value {
}
case cadence.Enum:
return importCompositeValue(
common.CompositeKindStructure,
Copy link
Member

Choose a reason for hiding this comment

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

👍

runtime/runtime.go Outdated Show resolved Hide resolved
runtime/argument_validation.go Outdated Show resolved Hide resolved
runtime/argument_validation.go Outdated Show resolved Hide resolved
runtime/argument_validation.go Outdated Show resolved Hide resolved
runtime/argument_validation.go Outdated Show resolved Hide resolved
runtime/argument_validation.go Outdated Show resolved Hide resolved
runtime/argument_validation.go Outdated Show resolved Hide resolved
runtime/argument_validation.go Outdated Show resolved Hide resolved
runtime/argument_validation.go Outdated Show resolved Hide resolved
@SupunS SupunS marked this pull request as draft April 1, 2021 18:22
@SupunS SupunS force-pushed the supun/improve-import-export-3 branch 3 times, most recently from 059ff4c to 36327c9 Compare April 2, 2021 07:44
@SupunS SupunS marked this pull request as ready for review April 2, 2021 07:46
@SupunS
Copy link
Member Author

SupunS commented Apr 2, 2021

@turbolent Thanks for the review!

As suggested, I moved the conformance checking to the interpreter.Value by introducing the following two methods:

  • ConformsToDynamicType(dynamicType DynamicType) bool
  • conformsToSemaType(semaType sema.Type) bool - This is a package-private method because we should discourage using it directly, because:
    • It doesn't check for subtyping. It is handled by a wrapper method (ValueConformsToSemaType) to avoid repetitive subtyping checks. Anyone who wishes to use this functionality should use ValueConformsToSemaType function instead.
    • It is currently only implemented for the values that are importable. For the rest, e.g: FunctionValue, it doesn't do a deep value equality (we can gradually add these, but doesn't require for now).

Can you please have a look at the new changes too?

Copy link
Member

@turbolent turbolent left a comment

Choose a reason for hiding this comment

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

Thank you for refactoring this @SupunS!

I thought about this a bit more and have the feeling this could be simplified a lot:
Currently adding this feature requires a lot of code to be added, but we already have most of the same checks in interpreter.IsSubType, the function that validates if a dynamic type (which should have all necessary information about a value) to a static type.

OK If I'll try to see if I can maybe reduce the code a bit and rely on what we already have? I'd open another PR against this one

Comment on lines 1252 to 1254
`pub fun main(arg: %[1]s)%[2]s {

if !arg.isInstance(Type<%[1]s>()) {
Copy link
Member

Choose a reason for hiding this comment

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

Good idea to check both argument validation (value conforms to static type) and also check dynamic type conformance 👍


t.Parallel()

var argumentPassingTests = []argumentPassingTest{
Copy link
Member

Choose a reason for hiding this comment

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

👍

Comment on lines +5929 to +5826
// Here it is assumed that imported values can only have static fields values,
// but not computed field values.
if v.Fields.Len() != len(compositeType.Fields) {
Copy link
Member

Choose a reason for hiding this comment

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

👍

runtime/interpreter/value.go Outdated Show resolved Hide resolved
Comment on lines 5914 to 5935
compositeType, ok := dynamicType.(CompositeDynamicType)
return ok && ValueConformsToSemaType(v, compositeType.StaticType)
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if we should include composites' fields' dynamic types in the composite dynamic type, just like we include the dynamic types of arrays' elements, and then check them here?

Copy link
Member Author

@SupunS SupunS Apr 6, 2021

Choose a reason for hiding this comment

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

Yup, that would be ideal.

If we have that, we can also get rid of all the value.conformsToSemaType() methods, because this is the only entry point to that method. For the numeric types, we could use isSubType()

runtime/interpreter/value.go Outdated Show resolved Hide resolved
}
}

func (v PathValue) conformsToSemaType(semaType sema.Type) bool {
Copy link
Member

Choose a reason for hiding this comment

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

👍

@SupunS
Copy link
Member Author

SupunS commented Apr 5, 2021

Thank you for refactoring this @SupunS!

I thought about this a bit more and have the feeling this could be simplified a lot:
Currently adding this feature requires a lot of code to be added, but we already have most of the same checks in interpreter.IsSubType, the function that validates if a dynamic type (which should have all necessary information about a value) to a static type.

OK If I'll try to see if I can maybe reduce the code a bit and rely on what we already have? I'd open another PR against this one

Sure, please do!

I also had a look at the isSubType() method - why I couldn't use it because it mostly does a nominal type check, whereas here we actually do sort of a structural type check. But maybe worth looking from a fresh pair of eyes!

Also maybe its worth merging #732 prior to this, as it also removes a few (a lot, infact) changes added by this PR (pretty much all the numeric types get reduced to just two)

UPDATE: It doesn't affect much of the changes, as the refactoring was mostly for the types, and has only a slight impact/conflict on the values.

@turbolent
Copy link
Member

I also had a look at the isSubType() method - why I couldn't use it because it mostly does a nominal type check, whereas here we actually do sort of a structural type check. But maybe worth looking from a fresh pair of eyes!

Right, I was mostly thinking the same, but then realized how much overlap / duplication there is and it might be good to re-consider.

Also maybe its worth merging #732 prior to this,

Please do @SupunS!

@SupunS SupunS force-pushed the supun/improve-import-export-3 branch 2 times, most recently from 8d1a6d5 to d44e8d1 Compare April 6, 2021 03:20
@turbolent
Copy link
Member

@SupunS Opened #776 against this PR to reduce the code, let me know what you think!

SupunS and others added 5 commits April 7, 2021 10:56
use the same combination of dynamic type check and check that the value
conforms to the dynamic type check it claims to be when checking if a
composite value conforms to a composite dynamic type
@SupunS SupunS force-pushed the supun/improve-import-export-3 branch from c4b03d5 to cdcb062 Compare April 7, 2021 05:26
@SupunS
Copy link
Member Author

SupunS commented Apr 7, 2021

Thanks, @turbolent for the cleanup! I merged your PR, and synched/rebased this branch with the master.

Opened #777 to handle the potential cyclic references.

runtime/convertValues.go Outdated Show resolved Hide resolved
Copy link
Member

@turbolent turbolent left a comment

Choose a reason for hiding this comment

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

Looks good, great work! 👍

@SupunS SupunS merged commit 2881963 into master Apr 8, 2021
@SupunS SupunS deleted the supun/improve-import-export-3 branch April 8, 2021 03:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Reject malformed values from being imported
2 participants