Prevent "input" function from calling functions or accessing variables - matlab

Considering the following code
x = input('Input an array: ');
If the user types [1 2 3], variable x will be assigned that numeric vector. Similarly, if they type {1, [2 3], 'abc'}, variable x will be a cell array containing those values. Fine.
Now, if the user types [sqrt(2) sin(pi/3)], variable x will be assigned the resulting values: [1.414213562373095 0.866025403784439]. That's because the provided data is evaluated by 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. [...]
This can cause problems. For example, what happens if the user types addpath('c:\path\to\folder') as input? Since the input is evaluated, it's actually a
command which will be executed by Matlab. So the user can get to add a folder to the path. Worse yet, if they input path(''), the path will be effectively changed to nothing, and Matlab will stop working properly.
Another potential source of problems is that
[...] To evaluate expressions, input accesses variables in the current workspace.
For example, if the user inputs fprintf(1,'%f', varname) and varname is an existing numeric array, the user will know its current value.
This behaviour is probably by design. Users of a Matlab program are trusted when inputting data, much like they are trusted not to press Control-C to halt the program (and then issue all commands or inspect all variables they like!).
But in certain cases the programmer may want to have a more "secure" input function, by which I mean
prevent any function calls when evaluating user
input; and
prevent the input from accessing variables of the program.
So [1 2] would be valid input, but [sqrt(2) sin(pi/3)] or path('') would not because of item 1; and [1 2 3 varname(1)] would be invalid too because of item 2.

I have found a not very satisfactory solution (and I'd love to read about a better one). It uses a semi-documented function and implies saving the user input to a temporary file. The function, referred to in Yair Altman's blog, is getcallinfo. According to 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.
This function solves issue 1 (prevent function calls). As for issue 2 (prevent access to variables), it would suffice to evaluate the input within a function, so that it can't see other variables. Apparently (see example 2 below), getcallinfo detects not only called functions, but variables too. Anyway, it's probably a good idea to do the evaluation in the isolated scope of a function.
The procedure is then:
Use the string version of input to prevent evaluation:
x = input('Input an array: ', 's');
Save the string to a file:
filename = 'tmp.m';
fid = fopen(filename,'w');
fprintf(fid, '%s',x);
fclose(fid);
Check the input string with getcallinfo to detect possible function calls:
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
where evalinput is the following function
function x = evalinput(x)
x = eval(x);
Example 1
Consider
x = input('Input an array: ', 's');
with user input
[sqrt(2) sin(pi/3)]
Then
filename = 'tmp.m';
fid = fopen(filename,'w');
fprintf(fid, '%s',x);
fclose(fid);
gci = getcallinfo(filename);
produces a non-empty gci.calls.fcnCalls.names,
>> gci.calls.fcnCalls.names
ans =
'sqrt' 'sin' 'pi'
which tells us that the user input would call functions sqrt, sin and pi if evaluated. Note that operators such as / are not detected as functions.
Example 2
y = [10 20 30];
x = input('Input an array: ', 's');
User enters
[1 y y.^2]
Then
filename = 'tmp.m';
fid = fopen(filename,'w');
fprintf(fid, '%s',x);
fclose(fid);
gci = getcallinfo(filename);
produces
>> gci.calls.fcnCalls.names
ans =
'y' 'y'
So variables are detected by getcallinfo as if they were functions.

If I understand your question correctly, it is possible to use regular expressions to accomplish what you are trying to do.
No function or variable calls
At its simplest, this checks to making sure there are no alphabetical characters in the input string. The expression would then be, for x containing input:
expr = '[a-zA-Z]';
x = input('Input an array: ', 's');
valid = isempty(regexp(x,expr));
This alone works for the few examples you give above.
Allowing some functions or variables
Suppose you want to allow the user to access some variables or functions, maybe simple trig functions, or pi or what have you, then it's no longer so simple. I've been playing around with an expression like below:
expr = '(?!cos\(|pi|sin\()[a-zA-Z]+
But it doesn't quite do what is expected. It will match in( in sin. If you know regex better than I, you can massage that to work properly.
Otherwise, an alternative would be to do this:
isempty(regexp(regexprep(x,'(sin\(|cos\(|pi|x)',''),expr))
so that you remove the strings you are interested in.
Hope this helps.
Update: In order to allow imaginary/exp values, and paths
The new expression to match becomes
expr = '[iIeE][a-zA-Z]+';
This ignores i/I and e/E (you can augment this as you see fit). You can also do a two character limit by switching to \{2,}, though I people can still have one character anonymous functions..
The other part, to check for input becomes:
isempty(regexp(regexprep(x,'(sin\(|cos\(|pi|x|''(.*?)'')',''),expr))
now you can exclude custom functions (you can always have this as an array and join them together by a |) and paths.
Here are a few examples tested along with the usual:
Passes
'[1+2i, 34e12]'
'''this is a path'''
'[cos(5), sin(3+2i)]'
Fails
'[1+2ii, 34e12]'
'this is not a path'
'''this is a path'' this is not'

Related

What does a function with this ~ mean? (e.g. function=f(~, x, y))

I am doing another coursera assignemnt, this time with aerial robotics. I have to program a pd controller using the matlab ode45 (ordinary diff. equation). And the file that has to contain this code gets called as follows:
pd_controller(~, s, s_des, params)
I searched around but couldn't find anthing that explain this to me and how it works.
In the main program the function is called with a time variable which I would need for my ODE:
controlhandle(t, s, s_des, params)
Where this controlhandle is the functionhandler for pd_controller.
So, what does this mean? And can I access whatever is behind ~?
Besides:
I found one example, but the other around. A function, let's call it function = f(a,b) was called with f(~, b) where a and b has been declared inside the function.
The symbol is called a tilde, and it signifies that you are ignoring that input argument.
See the documentation here: https://mathworks.com/help/matlab/matlab_prog/ignore-function-inputs.html
In your case, the function controlhandle will not be passed a t variable, and probably has (should have) some check for this and perhaps a default t if none is given.
This works the same with output arguments, for example if you want the index of a max in an array, but not the max itself, you would use
a = [pi, 3.6, 1];
[~, idx] = max(a); % idx = 2, we don't know what the max value is
It means you don't need pass this parameter in this function call. Also, you can use it in the output of some functions too. For example:
A = [1 4 2 2 41];
[~, B] = sort(A);
this means you don't need the second output, and you can ignore that.
In your case, when no value sent for the first parameter t, probably the function acts on a default value for t in his computation.
Also, you can find more about that in matlab documentation.
I should have mentioned that this post exists as an answer, but it might be here instead.

How to share variables between different m files in Matlab

I have three m files using the same variables and carrying out calculations on these variables. I have made an index m file in which i have declared all the variables and I can share the variables to the remaining m files using the variable names. My problem is that the variable names change too often and then I have to change the variable names in all these files manually. How can I make a Matlab script which can automatically get the variable names and value from the index m file and put these to the remaining m files.
I feel like you just need a little example from where you could go on so here we go:
First calling each value with a different variable name. if you have a lot of values of the same type a array is easier like:
A0=0; A1=6; A2=12 %each one with its own name
B=zeros(16,1); %create an array of 16 numbers
B(1)= 0; %1 is the first element of an array so care for A0
B(2)= 6;
B(8)= 12;
disp(B); % a lot of numbers and you can each address individually
disp(B(8)); %-> 12
you can put all that in your script and try it. Now to the function part. Your function can have input, output, neither or both. If you just want to create data you wont need an input but an output.
save this as myfile1.m:
function output = myfile1()
number=[3;5;6]; %same as number(1)=3;number(2)=5;number(3)=6
%all the names just stay in this function and the variable name is chosen in the script
output = number; %output is what the file will be
end
and this as myfile2.m
function output = myfile2(input)
input=input*2;%double all the numbers
%This will make an error if "input" is not an array with at least 3
%elements
input(3)=input(3)+2; %only input(3) + 2;
output = input;
end
and now try
B=myfile1() %B will become the output of myfile1
C=myfile2(B) %B is the input of myfile2 and C will become the output
save('exp.mat','C')
I hope this will get you started.

Trouble accepting input in MATLAB for anonymous functions

I have my function working if replace my input with a real function. However, when I change it like below, it asks me to input a function about like ten times and then outputs the answer.
I'm guessing this has to do with accepting functions as anonymous from a user? I'm not too sure what is going on. Thank you. This is my code:
f = #(x) input('Input a function');
A = [0 2];
z = myBisection(f,A);
With x.^2+3.*x-4 as my f function and the answer being 1.001
This is because you're not applying the right methodology for accepting inputs from input. What you are actually doing with f is that you're creating an anonymous function where if you run this, it will then ask you for input from the user. If you actually typed in this statement with your f variable as is, nothing would happen. Something would only happen if you typed in f() (or technically, f can be any input, but because the input variable for the anonymous function isn't being used in how you specified it, we can get away with specifying no inputs) in the command prompt to call this function, and then pushed ENTER. Even when you do this, the output of this function would only store a string, and you need to use this to create an anonymous function.
To fix this, what I would do is use input to store your function as a string. Take note that you need to add a second parameter for input, which is a string flag 's'. Without this, input would be expecting a number, and this obviously wouldn't work. After this, use str2func to turn this into an anonymous function, and then run your bisection method. str2func accepts in a string, and then converts that string into an actual MATLAB function and you can now use this for your purposes. By accepting your anonymous function as a string, you can place any operators you want to your heart's content, so long as the way you place them are syntactically valid. Also, make sure that your function is defined in terms of x like your example in your post.
As such do this:
funcString = input('Input a function: ', 's'); %// Make sure you specify 's'!
f = str2func(['#(x) ' funcString]);
A = [0 2];
z = myBisection(f, A);
Put this inside a .m file, then run this file. It should behave like you are expecting.

MATLAB cell array of function handles - How does it work?

I am trying to understand the following commands of a MATLAB script :
global operatorObj
calcEVR_handles = operatorObj.calcEVR_handles;
m = operatorObj.nInputs
E = zeros(m,1);
V = zeros(m,1);
R = zeros(m,m);
for i=1:m
[E(i), V(i), R(i,i)] = calcEVR_handles{i}(t,x);
end
What can calcEVR_handles be, if t is a float and x is a vector?
calcEVR_handles (to me) looks like a cell array where each element is a handle to a function. Each element in calcEVR_handles is an anonymous function that takes in a single value t and a single vector x. As such, by doing calcEVR_handles{i}, you would access the corresponding function stored at the ith element in the cell array. Once you have access, you then pass your parameters to this function and it gives you those three outputs.
To show you an example of this working, consider the following cell array that works similarly to calcEVR_handles.
calcCellFunc = {#sin, #cos, #tan};
This is a three element cell array, where each element is a handle to a function. The # is a special character in MATLAB that denotes that you are creating a handle to a function. It's also used to create anonymous functions, but let's shelve that for this answer. You can read more about it here if you want to delve into more detail regarding this.
Back to our cell array of handles, we will make handles for sin, cos and tan. You can then iterate over your cell array by accessing the function you want by calcCellFunc{idx} where idx is the element you want in the cell array. This will ultimately give you the function stored at index idx. Once you do that, you can then call the function and specify whatever inputs you want (or none if it doesn't take any inputs). Here's a quick example for you. Let's create a random 5 x 5 matrix, and run through each function with this matrix serving as the input. We then take each of these outputs and store them into a corresponding slot in an output cell array. As such:
rng(123); %// Set seed for reproducibility
M = rand(5);
calcCellFunc = {#sin, #cos, #tan};
out = cell(1, numel(calcCellFunc)); %// To store the results for each function
for idx = 1 : numel(calcCellFunc)
out{idx} = calcCellFunc{idx}(M); %// Get the function, then pass
%// the matrix M to it
end
If you want to make things clear, you could split up the out statement to this instead:
func = calcCellFunc{idx}; %// Get access to the function
out{idx} = func(M); %// Pass M to this function
If you're new to handles / anonymous functions, you should probably use the above code first to make it explicitly clear on what MATLAB is doing. You are first getting access to the function you want that is stored in the cell array, and then you pass your arguments to this function.
If we display the output, we get:
>> celldisp(out)
out{1} =
0.6415 0.4106 0.3365 0.6728 0.5927
0.2823 0.8309 0.6662 0.1815 0.7509
0.2249 0.6325 0.4246 0.1746 0.6627
0.5238 0.4626 0.0596 0.5069 0.5737
0.6590 0.3821 0.3876 0.5071 0.6612
out{2} =
0.7671 0.9118 0.9417 0.7398 0.8054
0.9593 0.5564 0.7458 0.9834 0.6604
0.9744 0.7745 0.9054 0.9846 0.7489
0.8518 0.8866 0.9982 0.8620 0.8191
0.7522 0.9241 0.9218 0.8619 0.7502
out{3} =
0.8363 0.4503 0.3573 0.9094 0.7359
0.2942 1.4934 0.8932 0.1845 1.1370
0.2308 0.8167 0.4690 0.1773 0.8850
0.6149 0.5218 0.0597 0.5880 0.7004
0.8761 0.4135 0.4205 0.5884 0.8814
The first element of the output cell array has the output when you pass M to sin, the second when you pass M to cos, and the third when you pass M to tan.
So the next question you're asking... why is this useful?
Point #1 - Nix the copying and pasting
This kind of code writing is very useful because if you want to use the same inputs and supply them to many different functions, we would naturally be inclined to do some copying and pasting. Take each of your function names, and create a single line for each. Each line would call the corresponding function you want, followed by the input arguments. This can become quite tedious, and so one smart way to do it would be to place your function name as a handle into a cell array, and to write one for loop that goes over all of the functions dynamically. You could even explore cellfun and escape using the for loop to iterate over all of the function handles too, but I'll leave that for you to read up on.
In this way, you have very maintainable code and if you want to remove functions that don't need to be run, just remove the handles from the cell array rather than scrolling down to where the line that invokes this function is located and removing that.
This is actually a very common technique in computer science / software engineering in general. In fact, this is actually quite close to what are known as function pointers. This is MATLAB's cheap way of doing it, but the logic behind this is essentially the same.
Point #2 - Higher Order Functions
Another way this is useful is if you have a function where one (or more than one!) of the inputs is a function, and you also specify inputs into this function as additional parameters to this function. This is what is known as a higher order function. The outputs would be based on using this input function, and the additional inputs you specify to it and the outputs are based on using this input function and the inputs you specify for this function.
One very good example is the fzero function in MATLAB. The goal is to find the root of a non-linear function, and the first parameter is a handle to a function that you specify. The base behaviour behind how fzero works is the same no matter what the function is. All you have to do is specify the function you want to solve and the initial guess of where you think this root is.
All in all, anonymous functions are very useful.

Matlab function handle workspace shenanigans

In short: is there an elegant way to restrict the scope of anonymous functions, or is Matlab broken in this example?
I have a function that creates a function handle to be used in a pipe network solver. It takes as input a Network state which includes information about the pipes and their connections (or edges and vertices if you must), constructs a large string which will return a large matrix when in function form and "evals" that string to create the handle.
function [Jv,...] = getPipeEquations(Network)
... %// some stuff happens here
Jv_str = ['[listConnected(~endNodes,:)',...
' .* areaPipes(~endNodes,:);\n',...
anotherLongString,']'];
Jv_str = sprintf(Jv_str); %// This makes debugging the string easier
eval(['Jv = #(v,f,rho)', Jv_str, ';']);
This function works as intended, but whenever I need to save later data structures that contain this function handle, it requires a ridiculous amount of memory (150MB) - coincidentally about as much as the entire Matlab workspace at the time of this function's creation (~150MB). The variables that this function handle requires from the getPipeEquations workspace are not particularly large, but what's even crazier is that when I examine the function handle:
>> f = functions(Network.jacobianFun)
f =
function: [1x8323 char]
type: 'anonymous'
file: '...\pkg\+adv\+pipe\getPipeEquations.m'
workspace: {2x1 cell}
...the workspace field contains everything that getPipeEquations had (which, incidentally is not the entire Matlab workspace).
If I instead move the eval statement to a sub-function in an attempt to force the scope, the handle will save much more compactly (~1MB):
function Jv = getJacobianHandle(Jv_str,listConnected,areaPipes,endNodes,D,L,g,dz)
eval(['Jv = #(v,f,rho)', Jv_str, ';']);
Is this expected behavior? Is there a more elegant way to restrict the scope of this anonymous function?
As an addendum, when I run the simulation that includes this function several times, clearing workspaces becomes painfully slow, which may or may not be related to Matlab's handling of the function and its workspace.
I can reproduce: anonymous functions for me are capturing copies of all variables in the enclosing workspace, not just those referenced in the expression of the anonymous function.
Here's a minimal repro.
function fcn = so_many_variables()
a = 1;
b = 2;
c = 3;
fcn = #(x) a+x;
a = 42;
And indeed, it captures a copy of the whole enclosing workspace.
>> f = so_many_variables;
>> f_info = functions(f);
>> f_info.workspace{1}
ans =
a: 1
>> f_info.workspace{2}
ans =
fcn: #(x)a+x
a: 1
b: 2
c: 3
This was a surprise to me at first. But it makes sense when you think about it: because of the presence of feval and eval, Matlab can't actually know at construction time what variables the anonymous function is actually going to end up referencing. So it has to capture everything in scope just in case they get referenced dynamically, like in this contrived example. This uses the value of foo but Matlab won't know that until you invoke the returned function handle.
function fcn = so_many_variables()
a = 1;
b = 2;
foo = 42;
fcn = #(x) x + eval(['f' 'oo']);
The workaround you're doing - isolating the function construction in a separate function with a minimal workspace - sounds like the right fix.
Here's a generalized way to get that restricted workspace to build your anonymous function in.
function eval_with_vars_out = eval_with_vars(eval_with_vars_expr, varargin)
% Assign variables to the local workspace so they can be captured
ewvo__reserved_names = {'varargin','eval_with_vars_out','eval_with_vars_expr','ewvo__reserved_names','ewvo_i'};
for ewvo_i = 2:nargin
if ismember(inputname(ewvo_i), ewvo__reserved_names)
error('variable name collision: %s', inputname(ewvo_i));
end
eval([ inputname(ewvo_i) ' = varargin{ewvo_i-1};']);
end
clear ewvo_i ewvo__reserved_names varargin;
% And eval the expression in that context
eval_with_vars_out = eval(eval_with_vars_expr);
The long variable names here hurt readability, but reduce the likelihood of collision with the caller's variables.
You just call eval_with_vars() instead of eval(), and pass in all the input variables as additional arguments. Then you don't have to type up a static function definition for each of your anonymous function builders. This'll work as long as you know up front what variables are actually going to be referenced, which is the same limitation as the approach with getJacobianHandle.
Jv = eval_with_vars_out(['#(v,f,rho) ' Jv_str],listConnected,areaPipes,endNodes,D,L,g,dz);
Anonymous functions capture everything within their scope and store them in the function workspace. See MATLAB documentation for anonymous functions
In particular:
"Variables specified in the body of the expression. MATLAB captures these variables and holds them constant throughout the lifetime of the function handle.
The latter variables must have a value assigned to them at the time you construct an anonymous function that uses them. Upon construction, MATLAB captures the current value for each variable specified in the body of that function. The function will continue to associate this value with the variable even if the value should change in the workspace or go out of scope."
An alternative workaround to your problem, is to use the fact that the matlab save function can be used to save only the specific variables you need. I have had issues with the save function saving way too much data (very different context from yours), but some judicial naming conventions, and use of wildcards in the variables list made all my problems go away.