考虑以下代码
x = input('Input an array: ');
如果用户键入 [1 2 3]
,变量 x
将被分配给该数字向量。同样,如果他们键入 {1, [2 3], 'abc'}
,变量 x
将是包含这些值的元胞数组。很好。
现在,如果用户键入 [sqrt(2) sin(pi/3)]
,变量 x
将被分配结果值:[1.414213562373095 0.866025403784439]
。这是因为提供的数据由 input
评估 :
input
Prompt for user input.
result = input(prompt)
displays theprompt
string on the screen, waits for input from the keyboard, evaluates any expressions in the input, and returns the value inresult
. [...]
这可能会导致问题。例如,如果用户键入 addpath('c:\path\to\folder')
作为输入会发生什么?由于对输入进行了评估,它实际上是一个
将由 Matlab 执行的命令。因此用户可以将文件夹添加到路径中。更糟糕的是,如果他们输入 path('')
,路径实际上将变为空,Matlab 将停止正常工作。
另一个潜在的问题来源是
[...] To evaluate expressions,
input
accesses variables in the current workspace.
例如,如果用户输入fprintf(1,'%f', varname)
并且varname
是一个现有的数值数组,用户将知道它的当前值.
此行为可能是设计使然。 Matlab 程序的用户在输入数据时是受信任的,就像他们被信任不会按 Control-C 来停止程序(然后发出所有命令或检查所有变量)一样他们喜欢!)。
但在某些情况下,程序员可能希望拥有更“安全”的input
函数,我的意思是
- 在评估用户时阻止任何函数调用 输入;和
- 防止输入访问程序的变量。
因此 [1 2]
将是有效输入,但是 [sqrt(2) sin(pi/3)]
或 path('')
不会因为第 1 项;并且 [1 2 3 varname(1)]
也会因为第 2 项而无效。
最佳答案
我找到了一个不太令人满意的解决方案(我很乐意阅读更好的解决方案)。它使用半文档化 函数并暗示将用户输入保存到临时文件。 Yair Altman's blog 中提到的函数, 是 getcallinfo
。根据help getcallinfo
:
getcallinfo
Returns called functions and their first and last lines
This function is unsupported and might change or be removed without notice in a future version.
此函数解决问题 1(防止函数调用)。至于问题 2(防止访问变量),在函数内评估输入就足够了,这样它就看不到其他变量。显然(参见下面的示例 2),getcallinfo
不仅检测被调用的函数,还检测变量。无论如何,在函数的隔离范围内进行求值可能是个好主意。
接下来的流程是:
使用
input
的字符串版本来防止求值:x = input('Input an array: ', 's');
将字符串保存到文件中:
filename = 'tmp.m'; fid = fopen(filename,'w'); fprintf(fid, '%s',x); fclose(fid);
使用
getcallinfo
检查输入字符串以检测可能的函数调用:gci = getcallinfo(filename); if ~isempty(gci.calls.fcnCalls.names) %// Input includes function calls: ignore / ask again / ... else x = evalinput(x); %// evaluate input in a function end
其中 evalinput
是下面的函数
function x = evalinput(x)
x = eval(x);
示例 1
考虑
x = input('Input an array: ', 's');
用户输入
[sqrt(2) sin(pi/3)]
然后
filename = 'tmp.m';
fid = fopen(filename,'w');
fprintf(fid, '%s',x);
fclose(fid);
gci = getcallinfo(filename);
产生一个非空的gci.calls.fcnCalls.names
,
>> gci.calls.fcnCalls.names
ans =
'sqrt' 'sin' 'pi'
这告诉我们用户输入将调用函数 sqrt
、sin
和 pi
如果被评估。请注意,/
等运算符不会被检测为函数。
例子2
y = [10 20 30];
x = input('Input an array: ', 's');
用户输入
[1 y y.^2]
然后
filename = 'tmp.m';
fid = fopen(filename,'w');
fprintf(fid, '%s',x);
fclose(fid);
gci = getcallinfo(filename);
产生
>> gci.calls.fcnCalls.names
ans =
'y' 'y'
所以变量被 getcallinfo
检测到,就好像它们是函数一样。
关于matlab - 阻止 "input"函数调用函数或访问变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33124078/