diff --git a/Changelog.md b/Changelog.md index b77be4f39..aaadcae9d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -30,6 +30,7 @@ Bugfixes: * SMTChecker: Fix internal error on chain assignments using static fully specified state variables. * SMTChecker: Fix internal error when using user defined types as mapping indices or struct members. * SMTChecker: Fix internal error when deleting struct member of function type. + * TypeChecker: Fix bug where private library functions could be attached with ``using for`` outside of their declaration scope. ### 0.8.17 (2022-09-08) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 93558ff89..00c763a90 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3809,6 +3809,10 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor) m_errorReporter.fatalTypeError( 4731_error, path->location(), + SecondarySourceLocation().append( + "Function defined here:", + functionDefinition.location() + ), fmt::format( "The function \"{}\" does not have any parameters, and therefore cannot be attached to the type \"{}\".", joinHumanReadable(path->path(), "."), @@ -3816,6 +3820,27 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor) ) ); + if ( + functionDefinition.visibility() == Visibility::Private && + functionDefinition.scope() != m_currentContract + ) + { + solAssert(functionDefinition.libraryFunction()); + m_errorReporter.typeError( + 6772_error, + path->location(), + SecondarySourceLocation().append( + "Function defined here:", + functionDefinition.location() + ), + fmt::format( + "Function \"{}\" is private and therefore cannot be attached" + " to a type outside of the library where it is defined.", + joinHumanReadable(path->path(), ".") + ) + ); + } + FunctionType const* functionType = dynamic_cast(*functionDefinition.type()).withBoundFirstArgument(); solAssert(functionType && functionType->selfType(), ""); BoolResult result = normalizedType->isImplicitlyConvertibleTo( diff --git a/test/libsolidity/semanticTests/using/private_library_function.sol b/test/libsolidity/semanticTests/using/private_library_function.sol new file mode 100644 index 000000000..e14404921 --- /dev/null +++ b/test/libsolidity/semanticTests/using/private_library_function.sol @@ -0,0 +1,10 @@ +library L { + using {L.privateFunction} for uint; + function privateFunction(uint x) private pure returns (uint) { return x + 1; } + function f() public pure returns (uint) { + uint x = 1; + return x.privateFunction(); + } +} +// ---- +// f() -> 2 diff --git a/test/libsolidity/syntaxTests/using/private_library_function_inside_scope.sol b/test/libsolidity/syntaxTests/using/private_library_function_inside_scope.sol new file mode 100644 index 000000000..1f036d83b --- /dev/null +++ b/test/libsolidity/syntaxTests/using/private_library_function_inside_scope.sol @@ -0,0 +1,5 @@ +library L { + using {L.privateFunction} for uint; + function privateFunction(uint) private pure {} +} +// ---- diff --git a/test/libsolidity/syntaxTests/using/private_library_function_outside_scope.sol b/test/libsolidity/syntaxTests/using/private_library_function_outside_scope.sol new file mode 100644 index 000000000..2be2010c6 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/private_library_function_outside_scope.sol @@ -0,0 +1,12 @@ +library L { + function privateFunction(uint) private pure {} +} + +using {L.privateFunction} for uint; + +contract C { + using {L.privateFunction} for uint; +} +// ---- +// TypeError 6772: (73-90): Function "L.privateFunction" is private and therefore cannot be attached to a type outside of the library where it is defined. +// TypeError 6772: (127-144): Function "L.privateFunction" is private and therefore cannot be attached to a type outside of the library where it is defined.