//Cyber Battlefield/Programs – Loops

Up until now, each program we looked at had the property that when it ran, the interpreter executed as many statements as we put in the program, or possibly fewer once we introduced if's. That means that we as programmers have to write very long programs in order to get a lot of work out of the computer. Now we introduce loops, which allow short programs to instruct the computer to do a large amount of work.


Suppose we want to add the numbers from 1 to 10. Obviously we could write
... but that doesn't scale well to a program that adds up the numbers from 1 to 1,000. Or 1,000,000. Suppose we had variables var total = 0; and var k = 1;. we could imagine doing the following over and over: add k to total and increment k by 1. If we do this up to and including when k is 10, we will have added up the numbers from 1 to 10. In JavaScript, we execute a block over and over again using a while statement. Like this:
var total = 0;
var k = 1;
{                              \
  total = total + k;            | Loop
  k = k + 1;                    | Body
}                              /
The code inside the block is called the loop body, and it's repeated over and over. How long? Well, inside the ( )'s is the continuation condition, a boolean-valued expression, and as long as the continuation condition is true, the body continues to be executed. In this case, we want to loop as long as k is less than or equal to 10, which gives us this program:

Just as a reminder, here's what the above program looks like embedded in a web page.
Question: Can you modify this program to compute the sum from 1 to 1,000?
Question: Can you modify this program to compute the sum from 1 to a number input by the user?

The Danger of Infinite Loops

Make sure you're viewing this page in Google Chrome or Internet Explorer (allow the scripts to run!) ... Firefox is ungraceful, then move on. Below is a version of the number summing program — a dangerous version.
Run this program and enter 1000, and you'll see all looks well. Run it again and enter -1. Be prepared to reopen this page after it crashes! What happened? Well, the program can keep adding on to total all it likes, but we'll never get k to equal n + 1 because n equals -1. So we get an infinite loop. Chrome handles this nicely — after a short while it just kills the page. In Firefox, this binds up the whole browser, which is not fun. Moral of the story is: Watch out for infinite loops!

A Non-Trivial Example (and binary search)

Here's a non-trivial example of a program. It implements a simple game in which the program chooses a random integer from 1-100, and the user tries to guess it. A few things to note: First, Math.random() generates a random number in the range 0 to 1. Obviously we're not talking just whole numbers! Second, prompt( ) returns the value null when the user clicks Cancel. A null value means "nothing". Make sure you understand this program!
Problem: Modify the program so that it displays "Better luck next time" rather than "You did it!" if the user clicks Cancel.
Problem: Modify the program so that it keeps track of the number of guesses and displays that number along with its "You did it!"/"Better luck next time" message?
Problem: Modify the program so that the user only gets 10 guesses.

Is there an optimum strategy for this game? There is. Figure it out, or look up "binary search" on the web and see if you can figure it out. What's the fewest guesses in which you can guarantee getting the number right?

Real trouble: allowing the user to enter code

Here's a neat trick. JavaScript has a function eval( ) that takes a string as its argument and evaluates the string within the interpreter. So, eval("3 + 4") is 7. Or, more interestingly, eval(prompt("enter an expression")), which allows the user to enter an expression and have it evaluated. Below is a slightly modified version of the number guessing problem, in which the user's guess is evaluated with eval( ). If they guess a number, nothing is changed, since, for example, eval(5) is 5. This way however, they can enter a guess like this: if you've gotten to the point where the number is between 3 and 38, you might enter Math.floor((38 + 3)/2). The program would evaluate that. Try it out.

What seemed like an innocent feature to improve the user experience is, however, a real problem. Now we can cheat. Run the game and try entering the character N. Now we can win in one step, every time! What happened? Since the user can input any expression, he can input expressions that use the variables within the program's environment. Here's another fun one: try entering N = 1. Now not only can we win in one move, we can choose the "answer". Lots of security flaws result from allowing arbitrary code that originates from outside a program to run within the program.

The mysterious empty string

What's the length of the string "abc"? Three of course? How about "ab"? Two! How about "a"? One. Well is there a string of length zero? Yes! We define an empty string like this: "". It is a string of no characters — of length zero. Why would I want a string of nothing? Well ... European mathematicians of long ago couldn't see the value in having a "number" zero? Why would I want a number for nothing? Actually, we'll see a very common use of the empty string below, when we create a variable that's initially set to the empty string so that we can add on to it later.

A useful program: random password generation

There are two basic string operations in JavaScript that are really important:
  1. .length — whenever you have a string, you can stick a .length at the end of it to find out how long it is. So, for example, "foo".length is 3. If z is a variable of type string, z.length tells you its length.
  2. [ ] — you can pick individual characters out of a string using [ ]'s. The only trick is that the index you use in the [ ]'s starts at 0, not 1. Thus, "abcd"[0] → "a", "abcd"[1] → "b", "abcd"[2] → "c" and "abcd"[3] → "d". Note that the last valid index into a string is its length minus one!
The more "random" a password is, the more secure it is. Let's use JavaScript's Math.random() function to generate random passwords of six characters.
Exercise: Modify the program so the user specifies the length of the password.
Exercise: Modify the program so punctuation and mathematical characters can appear in the password.
An interesting exercise is to generate a truly random 7 or 8 character password and see whether you can remember it for a few minutes. I think you'll find that we humans don't do a good job of remembering random strings.
Try this from your command prompt
ssh mxxxxxx@rona.academy.usna.edu "pwgen -0 -A 8"
This should generate a pronounceable 8-character password. It should be much easier to remember!

Bugs in the JavaScript Interpreter and the 2008 PWN2OWN Contest
The bugs that we've looked at so far (possibility of infinite loops, bad input crashing programs, and unexpected input allowing us to cheat at games) are all problems with JavaScript programs. Only the writers and users of these programs need to worry about them. A much deeper and more worrisome problem arises when there is a bug in the JavaScript interpreter. When that happens, a malicious JavaScript program can take advantage of the bug in the interpreter to actually make the user's browser or even the user's PC do bad things.

Every year the security conference CanSecWest holds the PWN2OWN contest, where participants try to exploit (take advantage of) bugs in browsers in order to "PWN" a computer whose browser visited their web page. Essentially, you've pwned a computer if you can get it to execute shell commands of your choosing & preferably in an administrator/root shell. In 2008, one group took advantage of a bug in Apple's Safari browser's JavaScript interpreter to pwn a MacBook Air. In other words, the MacBook Air's browser followed a link to this groups evil web page, and two minutes later they were able to send shell commands to the MacBook Air and have it execute them. Check out this 2008 news article or, if you really want to know, you can look at this whitepaper by the team that created the hack.