Skip to content

Commit

Permalink
Fix for crash involving the use of private types used as default values
Browse files Browse the repository at this point in the history
This attempts to fix issues ponylang#4130 and ponylang#4153.

The issue was when a private type in another package was used as a default value in a method call.

Fix to ponylang#4130
Since it has been decided to treat this as a bug instead of a missing error, this PR implements the fix suggested by @ergl, namely using `lookup_try()` instead of lookup() in call.c's `check_partial_function_call()` since it allows to permit private types.

Fix to ponylang#4153
This is also a simply fix to lookup.c that prevents a potential segfault by a dereferencing of `opt` (`typecheck_t* t = &opt->check;`) *before* `opt != NULL` was checked. As pointed out by @SeanTAllen, opt should not be NULL to begin with when lookup_nominal is called, and instead, an assert should be added and the NULL checks in that function removed.
  • Loading branch information
stefandd committed Jul 27, 2022
1 parent f6e1b60 commit 527864d
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 25 deletions.
43 changes: 20 additions & 23 deletions src/libponyc/type/lookup.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ static deferred_reification_t* lookup_nominal(pass_opt_t* opt, ast_t* from,
ast_t* orig, ast_t* type, const char* name, bool errors, bool allow_private)
{
pony_assert(ast_id(type) == TK_NOMINAL);
pony_assert(opt != NULL);
typecheck_t* t = &opt->check;

ast_t* def = (ast_t*)ast_data(type);
AST_GET_CHILDREN(def, type_id, typeparams);
const char* type_name = ast_name(type_id);

if(is_name_private(type_name) && (from != NULL) && (opt != NULL)
&& !allow_private)
if(is_name_private(type_name) && (from != NULL) && !allow_private)
{
if(ast_nearest(def, TK_PACKAGE) != t->frame->package)
{
Expand Down Expand Up @@ -94,34 +94,31 @@ static deferred_reification_t* lookup_nominal(pass_opt_t* opt, ast_t* from,
case TK_FUN:
{
// Typecheck default args immediately.
if(opt != NULL)
AST_GET_CHILDREN(find, cap, id, typeparams, params);
ast_t* param = ast_child(params);

while(param != NULL)
{
AST_GET_CHILDREN(find, cap, id, typeparams, params);
ast_t* param = ast_child(params);
AST_GET_CHILDREN(param, name, type, def_arg);

while(param != NULL)
if((ast_id(def_arg) != TK_NONE) && (ast_type(def_arg) == NULL))
{
AST_GET_CHILDREN(param, name, type, def_arg);

if((ast_id(def_arg) != TK_NONE) && (ast_type(def_arg) == NULL))
{
ast_t* child = ast_child(def_arg);
ast_t* child = ast_child(def_arg);

if(ast_id(child) == TK_CALL)
ast_settype(child, ast_from(child, TK_INFERTYPE));
if(ast_id(child) == TK_CALL)
ast_settype(child, ast_from(child, TK_INFERTYPE));

if(ast_visit_scope(&param, pass_pre_expr, pass_expr, opt,
PASS_EXPR) != AST_OK)
return NULL;
if(ast_visit_scope(&param, pass_pre_expr, pass_expr, opt,
PASS_EXPR) != AST_OK)
return NULL;

def_arg = ast_childidx(param, 2);
def_arg = ast_childidx(param, 2);

if(!coerce_literals(&def_arg, type, opt))
return NULL;
}

param = ast_sibling(param);
if(!coerce_literals(&def_arg, type, opt))
return NULL;
}

param = ast_sibling(param);
}
break;
}
Expand All @@ -140,7 +137,7 @@ static deferred_reification_t* lookup_nominal(pass_opt_t* opt, ast_t* from,
return NULL;
}

if(is_name_private(name) && (from != NULL) && (opt != NULL) && !allow_private)
if(is_name_private(name) && (from != NULL) && !allow_private)
{
switch(ast_id(find))
{
Expand Down
4 changes: 2 additions & 2 deletions src/libponyc/verify/call.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ static bool check_partial_function_call(pass_opt_t* opt, ast_t* ast)
ast_id(call_error) == TK_NONE || ast_id(call_error) == TK_DONTCARE);

// Look up the original method definition for this method call.
deferred_reification_t* method_def = lookup(opt, receiver, ast_type(receiver),
ast_name(method));
deferred_reification_t* method_def = lookup_try(opt, receiver, ast_type(receiver),
ast_name(method), true); // allow private types
ast_t* method_ast = method_def->ast;
deferred_reify_free(method_def);

Expand Down

0 comments on commit 527864d

Please sign in to comment.