Javascript Jems - Self Modifying Code
Written by Ian Elliot   
Tuesday, 24 December 2013
Article Index
Javascript Jems - Self Modifying Code
Safer self-modification

Javascript, being an interpreted language, can modify its own code as it runs. Self-modifying code can be dangerous but you should know about it and how it works. If you would like to experiment,  read on.

 

When programming was a young subject and valves ruled the earth a very powerful but very scary technique was invented – self-modifying code.

The whole beauty of the stored program computer design was that the data and program were treated in the same way. A program plus the data it needed to work with were loaded into memory and the program simply accessed and modified the data as required.

This idea was so new and powerful that programmers often didn’t really distinguish between the program and the data and allowed one part of the program to modify another part of the program.

Self-modifying code can effectively re-write itself as it runs and as such you can guess that it’s powerful but you should also be able to see that it creates a nightmare for debugging and generally understanding what is going on.

After all, if code is self modifying, there is no simple static piece of code that can be read through to check it makes sense.

As a result self-modifying code not only fell out of favour, it was actively demonised as something that only really evil programming languages would allow you to do. So if you think that self-modifying code has just been invented and is something connected with the new wave of dynamic languages think again – it’s old but still relatively untamed.

After all of this you might be surprised to learn that JavaScript allows self-modifying code. Indeed most interpreted or dynamic languages do. The point being that self modification isn’t always bad – you just need to work hard to keep it under control and that means keep it simple.

 

jemsicon

Dynamic functions - function to string

The reason why JavaScript supports runtime modifiable code is that the program itself is just data stored in a variable. Consider the way you can define a function:

function myfunc1(){alert("MyFunc 1");

which is almost exactly equivalent to:

myFunc1=function(){alert("My Func 1")};

The second form looks like a variable assignment and indeed it is. If you don’t believe me try:

alert(myFunc1);

and you will see the text of the function just as if it was a string.

However MyFunc1 isn’t actually a string – it’s a Function object. What is going on here is that the Function object;s toString method is being called and this returns a string representation of the function:

alert(myFunc1.toString());

Although this isn’t guaranteed, it works in all the major browsers.

There is also a rather more non-standard method called toSource which works in Firefox but not in most other browsers. Also notice that you can’t see the source code for internally defined functions only user defined functions.

You can take a function and convert it into a string using:

myString=myFunc1.toString();
alert(myString);

or you can use the String object’s constructor and an implied call to the toString method:

myString=new String(myFunc1);

Of course now that you have the function represented as a string you can edit it in any way that you like.

For example, you can change the “1” into a “2” using:

myString=myString.replace("1","2");
alert(myString);

This changes what is stored in the string into:

function(){alert("My Func 2")};

Notice that this is a string and there is no way you can directly execute this new function, i.e.

myString();

doesn’t do anything.

How to make a string back into a function is our next challenge.

The round trip - string to function

The real question is how to get the string back into a function and there are a number of ways of doing this.

The most direct is to use the Function object’s constructor. If you write:

myFunc=new Function(“arg1”,“arg2”…“statements”);

the new function will be created with the specified arguments and statements.

Notice that the number of arguments can't be variable as the last string passed to the constructor is taken to be the body of the new function.

To use this with our string we simply have to strip off the “function()” part of the string. Unfortunately some browsers place a space between “function” and “()” and some don’t.

You can probably improve on this simple minded implementation of the constructor:

myFunc2=new Function(myString.
       replace("function()","")
             .replace("function ()",""));
myFunc2();

The easy way out is to simply attempt to replace there function followed by no space or followed by one space. In the real world you would use a regular expression. 

Notice that there are no parameters used in this function and writing a routine to convert any function in the form of a string into a real function using the Function object constructor is slightly more difficult as it involves a lot of string manipulation to get things in the correct form.

Fortunately there is an easier method based on using eval.

String To Function Using Eval

Before you get worried because you have heard that eval is evil - it isn't. eval is one of the more powerful features of JavaScript and many an interpreted language. As it is powerful it is capable of misuse and if used to process user or server input then it can be used to get the program to do things you never dreamed of. However this doesn't mean you can't use eval internally in a safe way. 

The eval function accepts a string of JavaScript statements and executes them as if they were within your program.

One of the problem is that programmers will often say such-and-such an instruction is dangerous - without saying why. In the case of eval the only danger is that some outside agent will feed in an expression that evaluates to something that you didn't expect or would have allowed had you expected it. In other words if the string to be evaluated has its origins in anyway influenced by the outside world then you have to make sure that they outside world doesn't manage to feed it a string that does something evil. You can do this by checking that the string to be evaluated is limited in some way - usually referred to as sanitising the input or you can simply find some less powerful way to achieve the same result i.e. don't use eval. 

If however the string to be evaluated originates within your program and is 100% under control then what could possibly go wrong?

So to convert a string to a function you simply use:

myString=myString.replace("1","2");
eval("myFunc2=" + myString);
myFunc2();

Which displays the alert box "MyFunc2". From this point on in the program myFunc2 behaves like a standard Function object. Notice that its scope is determined by the scope of the myFunc2 variable and the function only exists after the eval operation - i.e. there is no function hoisting. 

This completes the “round-trip” in the sense that you can now convert a function to a string, modify it and convert it back to a function or you can simply put a function together as a string as the program runs and convert it to a function when you want to use it.

 

Banner

 

This gives you the power to write self-modifying code of arbitrary complexity and the same tricks can be used to modify object methods just as easily.

 

 

<ASIN:0137054890>

<ASIN:0470526912>

<ASIN:1449381871>

<ASIN:1430230541>

<ASIN:0321683919>



Last Updated ( Thursday, 26 December 2013 )
 
 

   
RSS feed of all content
I Programmer - full contents
Copyright © 2014 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.