matlab - 阻止 "input"函数调用函数或访问变量

标签 matlab input user-input

考虑以下代码

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 the prompt string on the screen, waits for input from the keyboard, evaluates any expressions in the input, and returns the value in result. [...]

这可能会导致问题。例如,如果用户键入 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. 防止输入访问程序的变量

因此 [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 不仅检测被调用的函数,还检测变量。无论如何,在函数的隔离范围内进行求值可能是个好主意。

接下来的流程是:

  1. 使用 input 的字符串版本来防止求值:

    x = input('Input an array: ', 's');
    
  2. 将字符串保存到文件中:

    filename = 'tmp.m';
    fid = fopen(filename,'w');
    fprintf(fid, '%s',x);
    fclose(fid);
    
  3. 使用 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'

这告诉我们用户输入将调用函数 sqrtsinpi 如果被评估。请注意,/ 等运算符不会被检测为函数。

例子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/

相关文章:

c - C 中的 Matlab 引擎函数返回零

forms - 如何更改 TextField 值而不必先删除它(Flutter)

java - 更正输入文件以读取每一行

c# - 通知用户无效输入的常见做法是什么?

matlab - 将 N^2 个 3x3 矩阵串联成一个 3Nx3N 矩阵

matlab - 获取屏幕单位matlab以保存为pdf

java - MATLAB Compiler Runtime (MCR) 中的 JVM 有什么作用?

readline 不接受 Java 输入

c - 如何将用户输入限制为仅单个字符

命令行参数 C