Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion libpromises/fncall.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ Rlist *NewExpArgs(EvalContext *ctx, const Policy *policy, const FnCall *fp, cons
return RlistCopy(fp->args);
}

assert(fp != NULL);

const FnCallType *fn = FnCallTypeGet(fp->name);
if (fn == NULL)
{
Expand Down Expand Up @@ -101,7 +103,18 @@ Rlist *NewExpArgs(EvalContext *ctx, const Policy *policy, const FnCall *fp, cons
}
else
{
rval = ExpandPrivateRval(ctx, NULL, NULL, rp->val.item, rp->val.type);
const Bundle *caller_bundle = fp->caller ? PromiseGetBundle(fp->caller) : NULL;
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
const char *caller_ns = caller_bundle ? caller_bundle->ns : NULL;
rval = ExpandPrivateRval(ctx, caller_ns, NULL, rp->val.item, rp->val.type);
Comment thread
SimonThalvorsen marked this conversation as resolved.
/*
* Scope is intentinally left as NULL, since this function is called when expanding vars inside function-calls
* E.g. A bundle write, defined in a namespace "ns" with the var "file", then scope is already set (write)
* expression => read_module_protocol( "$(write.file)" );
* but the namespace needs to be added as it is missing.
*
* expression => read_module_protocol( "$($(this.namespace):write.file)" );
* would insert ns correctly without this fix since the internal ns would resolve first :ENT-10199
*/
assert(rval.item);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
###############################################################################
# ENT-10199 - namespace/scope resolution
#
# Data bundles live in ns_a, ns_b, default. Caller bundles live in ns_a, ns_b,
# default.
# Each caller tests:
# - bare same-bundle var -> always PASS
# - unqualified ref to data in ITS OWN namespace -> PASS post-fix
# - unqualified ref to data in the OTHER non-default ns -> FAIL always
# - unqualified ref to data in default -> FAIL always
# - explicit fully-qualified cross-ns ref -> always PASS
###############################################################################
# Default namespace
###############################################################################
bundle agent __main__
{
methods:
"data_default";
"ns_a:data_a";
"ns_b:data_b";
"caller_default";
"ns_a:caller_a";
"ns_b:caller_b";
"check";
}

bundle agent data_default
{
vars:
"val" string => "VALUE_FROM_DEFAULT";
}

bundle agent caller_default
{
vars:
"val" string => "LOCAL_DEFAULT";
"bare" string => format("%s", "$(val)");
"own_ns" string => format("%s", "$(data_default.val)");
"other_ns_a" string => format("%s", "$(data_a.val)");
"other_ns_b" string => format("%s", "$(data_b.val)");
"qualified_a" string => format("%s", "$(ns_a:data_a.val)");
"qualified_b" string => format("%s", "$(ns_b:data_b.val)");

reports:
"[caller_default] bare => '$(bare)' (expect: LOCAL_DEFAULT)";
"[caller_default] own_ns => '$(own_ns)' (expect: VALUE_FROM_DEFAULT - baseline, always worked)";
"[caller_default] other_ns_a => '$(other_ns_a)' (expect: unresolved - not a bug)";
"[caller_default] other_ns_b => '$(other_ns_b)' (expect: unresolved - not a bug)";
"[caller_default] qualified_a => '$(qualified_a)' (expect: VALUE_FROM_NS_A)";
"[caller_default] qualified_b => '$(qualified_b)' (expect: VALUE_FROM_NS_B)";
}

bundle agent check
{
classes:
# caller_a
"check_01"
expression => and(
isvariable("ns_a:caller_a.bare"),
strcmp("$(ns_a:caller_a.bare)", "LOCAL_A")
);

"check_02"
expression => and(
isvariable("ns_a:caller_a.own_ns"),
strcmp("$(ns_a:caller_a.own_ns)", "VALUE_FROM_NS_A")
);

"check_03" expression => not(isvariable("ns_a:caller_a.other_ns"));
"check_04" expression => not(isvariable("ns_a:caller_a.default_ns"));

"check_05"
expression => and(
isvariable("ns_a:caller_a.qualified"),
strcmp("$(ns_a:caller_a.qualified)", "VALUE_FROM_NS_B")
);

# caller_b
"check_06"
expression => and(
isvariable("ns_b:caller_b.bare"),
strcmp("$(ns_b:caller_b.bare)", "LOCAL_B")
);

"check_07"
expression => and(
isvariable("ns_b:caller_b.own_ns"),
strcmp("$(ns_b:caller_b.own_ns)", "VALUE_FROM_NS_B")
);

"check_08" expression => not(isvariable("ns_b:caller_b.other_ns"));
"check_09" expression => not(isvariable("ns_b:caller_b.default_ns"));

"check_10"
expression => and(
isvariable("ns_b:caller_b.qualified"),
strcmp("$(ns_b:caller_b.qualified)", "VALUE_FROM_NS_A")
);

# caller_default
"check_11"
expression => and(
isvariable("default:caller_default.bare"),
strcmp("$(default:caller_default.bare)", "LOCAL_DEFAULT")
);

"check_12"
expression => and(
isvariable("default:caller_default.own_ns"),
strcmp("$(default:caller_default.own_ns)", "VALUE_FROM_DEFAULT")
);

"check_13"
expression => not(isvariable("default:caller_default.other_ns_a"));

"check_14"
expression => not(isvariable("default:caller_default.other_ns_b"));

"check_15"
expression => and(
isvariable("default:caller_default.qualified_a"),
strcmp("$(default:caller_default.qualified_a)", "VALUE_FROM_NS_A")
);

"check_16"
expression => and(
isvariable("default:caller_default.qualified_b"),
strcmp("$(default:caller_default.qualified_b)", "VALUE_FROM_NS_B")
);

"check_17"
expression => and(
isvariable("ns_a:caller_a.qualified_a_a"),
strcmp("$(ns_a:caller_a.qualified_a_a)", "VALUE_FROM_NS_A")
);

"check_18" expression => not(isvariable("ns_a:caller_a.qualified_a_b"));

"check_19"
expression => and(
isvariable("ns_b:caller_b.qualified_a_a"),
strcmp("$(ns_b:caller_b.qualified_a_a)", "VALUE_FROM_NS_A")
);

"check_20" expression => not(isvariable("ns_b:caller_b.qualified_a_b"));

"all_passed"
expression => and(
check_01,
check_02,
check_03,
check_04,
check_05,
check_06,
check_07,
check_08,
check_09,
check_10,
check_11,
check_12,
check_13,
check_14,
check_15,
check_16,
check_17,
check_18,
check_19,
check_20
);

reports:
all_passed::
"$(this.promise_filename) Pass";

!all_passed::
"$(this.promise_filename) Fail";
}

###############################################################################
# DATA bundles
###############################################################################
body file control
{
namespace => "ns_a";
}

bundle agent data_a
{
vars:
"val" string => "VALUE_FROM_NS_A";
}

body file control
{
namespace => "ns_b";
}

bundle agent data_b
{
vars:
"val" string => "VALUE_FROM_NS_B";
}

###############################################################################
# CALLER in ns_a
###############################################################################
body file control
{
namespace => "ns_a";
}

bundle agent caller_a
{
vars:
"val" string => "LOCAL_A";
"bare" string => format("%s", "$(val)");
"own_ns" string => format("%s", "$(data_a.val)");
"other_ns" string => format("%s", "$(data_b.val)");
"default_ns" string => format("%s", "$(data_default.val)");
"qualified" string => format("%s", "$(ns_b:data_b.val)");
"qualified_a_a" string => format("%s", "$(ns_a:data_a.val)");
"qualified_a_b" string => format("%s", "$(ns_a:data_b.val)");

reports:
"[caller_a] bare => '$(bare)' (expect: LOCAL_A)";
"[caller_a] own_ns => '$(own_ns)' (expect: VALUE_FROM_NS_A - ENT-10199 Fixes this)";
"[caller_a] other_ns => '$(other_ns)' (expect: unresolved - not a bug)";
"[caller_a] default_ns => '$(default_ns)' (expect: unresolved - not a bug)";
"[caller_a] qualified => '$(qualified)' (expect: VALUE_FROM_NS_B)";
"[caller_a] qualified_a_a => '$(qualified_a_a)' (expect: VALUE_FROM_NS_A)";
"[caller_a] qualified_a_b => '$(qualified_a_b)' (expect: unresolved - not a bug)";
}

###############################################################################
# CALLER in ns_b
###############################################################################
body file control
{
namespace => "ns_b";
}

bundle agent caller_b
{
vars:
"val" string => "LOCAL_B";
"bare" string => format("%s", "$(val)");
"own_ns" string => format("%s", "$(data_b.val)");
"other_ns" string => format("%s", "$(data_a.val)");
"default_ns" string => format("%s", "$(data_default.val)");
"qualified" string => format("%s", "$(ns_a:data_a.val)");
"qualified_a_a" string => format("%s", "$(ns_a:data_a.val)");
"qualified_a_b" string => format("%s", "$(ns_a:data_b.val)");

reports:
"[caller_b] bare => '$(bare)' (expect: LOCAL_B)";
"[caller_b] own_ns => '$(own_ns)' (expect: VALUE_FROM_NS_B - ENT-10199 Fixes this)";
"[caller_b] other_ns => '$(other_ns)' (expect: unresolved - not a bug)";
"[caller_b] default_ns => '$(default_ns)' (expect: unresolved - not a bug)";
"[caller_b] qualified => '$(qualified)' (expect: VALUE_FROM_NS_A)";
"[caller_b] qualified_a_a => '$(qualified_a_a)' (expect: VALUE_FROM_NS_A)";
"[caller_b] qualified_a_b => '$(qualified_a_b)' (expect: unresolved - not a bug)";
}
Loading