Re: Use AS operators dinamically
Re: Use AS operators dinamically
- Subject: Re: Use AS operators dinamically
- From: has <email@hidden>
- Date: Wed, 6 Jan 2010 18:20:54 +0000
Thomas Fischer wrote:
> with due respect, but apart from the awkward quotes Matt's script isn't much shorter than the direct AppleScript I suggested:
>
> set myArray to {myVar, "starts with", "john"}
> set myAction to "return (\"" & item 1 of myArray & "\" " & item 2 of myArray & " \"" & item 3 of myArray & "\")"
> run script myAction
>
> without the appscript library loaded and the Appscript module included.
The appscript stuff in Matt's code was a red herring; ignore it. Here's a simpler demonstration:
$ irb
>> 2.send('+',2)
=> 4
> Or are there any side effects I overlooked?
Giant honking security holes:
set MyVar to "\", say \"u r haxored\", \""
set myArray to {myVar, "starts with", "john"}
set myAction to "return (\"" & item 1 of myArray & "\" " & item 2 of myArray & " \"" & item 3 of myArray & "\")"
run script myAction
I've not got time to write a fresh explanation, here's an earlier one I wrote in response to an email from Takaaki Naganoya on the subject:
----------------------------------------------------------------------
'run script', like 'do shell script' and all other 'eval' type functions, is inherently insecure because it allows arbitrary code to be freely executed. It is entirely up to the developer (in this case, you) to use it in a secure fashion. In code that takes arbitrary input from an external source (as yours does), this means being absolutely rigorous in sanitising all of those inputs.
Your script does marginally better than many in that it does at least sanitise the 'operatorCmd' input, rejecting it if it isn't one of your approved 'safe' values. Unfortunately, you forgot to sanitise the other inputs, which means that your script will break if, for example, any of those input strings contains a double quote mark, e.g.:
set myVar to {"John \"Smith", "Mike Smith", "Michael Jackson"}
Or, in the case of more malicious input:
set myVar to {"John \", say \"u r haxored\", \" Smith", "Mike Smith", "Michael Jackson"}
where 'say "u r haxored"' could be a command that wipes your hard disk or installs a trojan or any number of exceedingly nasty actions. Try running both of the above in your original script to see what I mean. That's the problem with security: you're either 100% secure or you're 100% insecure; there's no such thing as "nearly secure."
However, if you'd done it like this:
set myVar to {"John Smith", "Mike Smith", "Michael Jackson"}
set aList to retDynamicOperatedData(myVar, "ends with", "Smith")
--> {"John Smith", "Mike Smith"}
on retDynamicOperatedData(operand1, operatorCmd, operand2)
--Command Check
if operatorCmd is not in {"starts with", "ends with", "contains"} then return {}
--Make Dynamic Script
set aScript to "
on run {op1, op2}
return op1 " & operatorCmd & " op2
end run"
return run script aScript with parameters {operand1, operand2}
end retDynamicOperatedData
you'd have been fine: your operatorCmd input is properly sanitised before being turned into source code, and the other two values are now passed to the script to process as they are so require no special processing. Plus the code is a darn sight simpler, since you're not trying to mash AppleScript objects into their literal equivalents.
...
BTW, in situations where 'run script' is genuinely unavoidable, here's a variation on the above which avoids the need to pass your operands to the 'run script' command at all:
set scriptObj to run script "
script
on doEval(op1, op2)
return op1 " & operatorCmd & " op2
end doEval
end script"
return scriptObj's doEval(operand1, operand2)
That can be very useful when you want the script to process the original values, not copies (since all parameters to osax/application commands are automatically copied when they're packed into Apple events). For example, the following script is intended to set a record's property given the property name as string (sanitisation code emitted for clarity):
set propertyName to "foo"
set theRecord to {foo:false}
set aScript to "
on run (theRecord, theValue)
set " & propertyName & " of theRecord to theValue
end run"
run script aScript with parameters {theRecord, true}
return theRecord
--> {foo:false} -- Oops!
but clearly doesn't give the desired result, as the 'run script' command is working on a copy of the original record, not the original record itself. OTOH, by using the 'run script' command to manufacture script objects, your dynamically manufactured code can operate on the original record:
set propertyName to "foo"
set theRecord to {foo:false}
set scriptObj to run script "
script
on setProperty(theRecord, theValue)
set " & propertyName & " of theRecord to theValue
end doEval
end script"
scriptObj's setProperty(theRecord, true)
return theRecord
--> {foo:true} -- Yay!
That aside, for what the OP was doing, I would still use a straight conditional block - it may be less "clever", but as Brian Kernighan put it: "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it."
If you google "Little Bobby Tables" (or "injection attack" if you want the boring version), you'll also find that plenty of so-called "professional" programmers make the same mistakes, and learn a bit about how to avoid them yourself in future.
----------------------------------------------------------------------
To reiterate what Matt said: fancy dynamic stuff like 2.send('+',2) is trivial, fast, robust and less egregiously insecure in languages like Ruby, Python, ObjC, etc, as they were designed ground-up to support this kind of use. AppleScript wasn't, so if you think it's easy to do there then that's a sure sign you don't understand the problem well enough to solve it safely.
HTH
has
--
Control AppleScriptable applications from Python, Ruby and ObjC:
http://appscript.sourceforge.net
_______________________________________________
Do not post admin requests to the list. They will be ignored.
AppleScript-Users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
Archives: http://lists.apple.com/archives/applescript-users
This email sent to email@hidden