Great bug writers think alike

a.k.a. “A subtle bug from a perfect storm of HTTP, HTML, JavaScript, and DOM

My current work

I’m currently in the midst of implementing a new interface for creating new users. This is how it currently looks like:

The project membership table is created on the client side using JavaScript. The administrator adds and removes memberships (rows) without submitting the form.

HTML forms and HTTP, revisited

(Recall A simplified overview of HTML forms.) When the form is submitted over HTTP, all that is sent is a dictionary of key-value pairs. Each form element (text box, checkbox, select, etc.) generates at most one item for the dictionary, where the key is the name of the element (given by the name attribute) and the value is the string value of the element (“alice”, “pA55w0rd”, “on”, “viewer”, etc.).

Perhaps surprisingly, the dictionary’s keys need not be unique. For example, if there are two text boxes named “foo”, one with the value “bar” and one with the value “baz”, then the submitted form data would be “foo=bar, foo=baz” (or possibly “foo=baz, foo=bar”).

The tricky stuff: Client side

So for the form pictured above, the submitted information will be something along the lines of “username=roule, email=roulette@localhost, realname=Roulette, affiliation=Pani, password=01234567″… But wait! What about the membership table?

The first (but incorrect) idea that comes to mind is to give the same name for all elements in a column. For example, all the project selects would be named “project”, and all the role selects would be named “role”. The problem with this is that in the presence of multiple “project” and “role” keys, we don’t know which one was assoicated with which. A concrete example: Suppose John is a viewer in Alpha and a developer in Beta. The submitted form data would look like “project=Alpha, project=Beta, role=viewer, role=developer”, but with the entries being presented to the server in an arbitrary order. So it would be impossible to associate projects and roles uniquely.

Clearly then, the solution is to give each field a unique name. A simple method is to add a counter after the name – like “project0”, “project1”, “role0”, “role1”, etc.

The tricky stuff: Server side

How would the server process this information when it’s submitted? Assume that the client does not send the count of the number of rows. One way for the server to handle the variable number of rows is to start from a prearranged fixed number – 0 in this example – and process form fields and count upwards until the first n such that the submitted field “projectn” does not exist.

So far so good, right? But notice that on the client side, membership rows can be removed. Suppose that for simplicity, we don’t re-enumerate the remaining form fields. So if we had “project0”, “project1”, “project2” and then removed the middle entry, then we’d be left with “project0” and “project2”. Clearly, this interacts badly with the server side handler just described, since “project2” will be ignored. (Because “project1” does not exist, the server stops processing.)

Solutions

There are two relatively simple solutions to this problem:

  • Keep the client-side behaviour and modify the server-side behaviour. For each new row, give an auto-incrementing numerical suffix for the form fields. Do nothing special when removing rows. On the server, iterate through all form fields that have a name of the form “projectN“, where N is a number string. Ignore “gaps” in the numbering.
  • Modify the client-side behaviour and keep the server-side behaviour. When a row is removed, re-enumerate the rows that follow it. This is the solution that I picked, for no particular strong reason.

Great bug writers think alike

Now, if this problem were merely hypothetical, I wouldn’t have a good reason to write this rant-like-lengthed post about it. But it does already exist in DrProject! Namely, it manifests itself in the “Membership Preferences” section of the Edit User page and also on the current user’s Preferences page.

The offending server-side form handler code is found in register.py. (The complicated process of pinpointing this piece of code will be another story.)

Advertisements
Explore posts in the same categories: DrProject, Uncategorized

One Comment on “Great bug writers think alike”


  1. […] Qiyu Zhu has wrapped up the role editor. He’s learned enough about software development to add, “for now” :-)  He’d also like you to know that great bug writers think alike. […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: