Commit dbf552a
committed
Fix scoping of disciplines for certain special variables
Example reproducer:
function pathlocal
{
typeset PATH=LocalValue
print -r -- "in pathlocal: $PATH"
}
function PATH.get
{
.sh.value=MainShellValue
}
print -r -- "in main: $PATH"
pathlocal
Expected output:
in main: MainShellValue
in pathlocal: LocalValue
Actual output (before this commit):
in main: MainShellValue
in pathlocal: MainShellValue
Analysis:
Normally, when a local variable is defined using 'typeset' in a ksh
function, it is initialised from scratch as a regular variable,
even if it is a special variable in the local scope. For example,
after 'typeset RANDOM' in a ksh function, the local RANDOM variable
will not produce pseudorandom numbers.
The same applies to user-defined shell discipline functions. They
apply to the variable in the global scope, not to local variables,
unless they are defined in the local scope for that local variable.
However, for reasons of security and correctness, certain variables
must keep their standard C discipline functions even when redefined
in a local scope. These currently include IFS, PATH, SHELL, FPATH,
CDPATH, SECONDS, ENV, and all the locale-related variables (LANG,
LC_*). So these keep their default special properties even as local
variables. This is not very consistent, but it's necessary, for
example, to properly enforce the 'restricted' shell option, or to
be able to have different IFS field splitting behaviour or set a
different locale temporarily in a local scope.
These variables are defined in nv_cover() in init.c. This function
returns a pointer to the variable's current discipline function
stack if it is one of these specific variables, otherwise NULL.
Two code points in name.c use this to simply copy the discipline
function stack pointer from the global scope to the local scope.
And therein lies the problem. If an additional custom discipline
(usually a shell discipline function) is defined for the variable,
that one will carry over to the local scope, too. And that is both
incorrect, because the local variable is a new variable even though
it has the same name, and inconsistent, because variables not
listed in nv_cover() don't work that way.
src/cmd/ksh93/sh/init.c:
- Rename nv_cover() to nv_enforcedisc() for clarity.
- nv_enforcedisc(): Don't return a pointer to the listed variables'
existing discipline function stack (nvfun), but instead return a
pointer to their standard C discipline, as assigned by nv_init().
src/cmd/ksh93/sh/{name,subshell}.c:
- In nv_setlist() and nv_create(), where the nvfun pointer was
copied, instead call nv_stack() to initialise their discipline
function stack using the pointer returned by nv_enforcedisc();
this is what nv_init() does for their global scopes.
- No change is needed for the other nv_cover() calls (except for
calling the new name), because they only check for a non-NULL
result, and that hasn't changed.
src/cmd/ksh93/sh.1:
- Document the behaviour of special properties in local scopes.1 parent dd2a393 commit dbf552a
File tree
8 files changed
+91
-21
lines changed- src/cmd/ksh93
- include
- sh
- tests
8 files changed
+91
-21
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
5 | 13 | | |
6 | 14 | | |
7 | 15 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
144 | 144 | | |
145 | 145 | | |
146 | 146 | | |
147 | | - | |
| 147 | + | |
148 | 148 | | |
149 | 149 | | |
150 | 150 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
| 21 | + | |
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2553 | 2553 | | |
2554 | 2554 | | |
2555 | 2555 | | |
| 2556 | + | |
| 2557 | + | |
| 2558 | + | |
| 2559 | + | |
| 2560 | + | |
| 2561 | + | |
| 2562 | + | |
| 2563 | + | |
| 2564 | + | |
| 2565 | + | |
| 2566 | + | |
| 2567 | + | |
| 2568 | + | |
| 2569 | + | |
2556 | 2570 | | |
2557 | 2571 | | |
2558 | 2572 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1550 | 1550 | | |
1551 | 1551 | | |
1552 | 1552 | | |
1553 | | - | |
| 1553 | + | |
| 1554 | + | |
1554 | 1555 | | |
1555 | | - | |
1556 | | - | |
1557 | | - | |
1558 | | - | |
1559 | | - | |
1560 | | - | |
| 1556 | + | |
| 1557 | + | |
| 1558 | + | |
| 1559 | + | |
| 1560 | + | |
| 1561 | + | |
| 1562 | + | |
| 1563 | + | |
| 1564 | + | |
| 1565 | + | |
| 1566 | + | |
| 1567 | + | |
| 1568 | + | |
| 1569 | + | |
| 1570 | + | |
| 1571 | + | |
| 1572 | + | |
| 1573 | + | |
1561 | 1574 | | |
1562 | 1575 | | |
1563 | 1576 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
594 | 594 | | |
595 | 595 | | |
596 | 596 | | |
| 597 | + | |
597 | 598 | | |
598 | 599 | | |
599 | 600 | | |
600 | 601 | | |
601 | | - | |
| 602 | + | |
| 603 | + | |
602 | 604 | | |
603 | 605 | | |
604 | 606 | | |
| |||
881 | 883 | | |
882 | 884 | | |
883 | 885 | | |
884 | | - | |
| 886 | + | |
885 | 887 | | |
886 | | - | |
| 888 | + | |
| 889 | + | |
| 890 | + | |
| 891 | + | |
| 892 | + | |
| 893 | + | |
887 | 894 | | |
888 | | - | |
889 | | - | |
| 895 | + | |
| 896 | + | |
890 | 897 | | |
891 | | - | |
892 | | - | |
893 | | - | |
894 | | - | |
895 | | - | |
| 898 | + | |
| 899 | + | |
| 900 | + | |
| 901 | + | |
| 902 | + | |
| 903 | + | |
896 | 904 | | |
897 | 905 | | |
898 | 906 | | |
| |||
2291 | 2299 | | |
2292 | 2300 | | |
2293 | 2301 | | |
2294 | | - | |
| 2302 | + | |
2295 | 2303 | | |
2296 | 2304 | | |
2297 | 2305 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
359 | 359 | | |
360 | 360 | | |
361 | 361 | | |
362 | | - | |
| 362 | + | |
363 | 363 | | |
364 | 364 | | |
365 | 365 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1769 | 1769 | | |
1770 | 1770 | | |
1771 | 1771 | | |
| 1772 | + | |
| 1773 | + | |
| 1774 | + | |
| 1775 | + | |
| 1776 | + | |
| 1777 | + | |
| 1778 | + | |
| 1779 | + | |
| 1780 | + | |
| 1781 | + | |
| 1782 | + | |
| 1783 | + | |
| 1784 | + | |
| 1785 | + | |
| 1786 | + | |
| 1787 | + | |
| 1788 | + | |
| 1789 | + | |
| 1790 | + | |
| 1791 | + | |
| 1792 | + | |
| 1793 | + | |
| 1794 | + | |
| 1795 | + | |
| 1796 | + | |
| 1797 | + | |
| 1798 | + | |
1772 | 1799 | | |
1773 | 1800 | | |
0 commit comments