|
|
|
| Hurry! Enter The Daily WTF's OMGWTF2 Contest by June 28th! - Prizes! Fame! Trophies! Do your worst: http://omg2.thedailywtf.com/ |
| « OUCH! | ISelfAware, Very Thorough, Crazy Hashmaps, and More » |
Back in the days of the first Internet Bubble, Tom received a call from his colleague Steve. They were both contractors, working for the same elite contracting company, and Steve had run into a problem with a Perl script he couldn't figure out. Tom, being a bit more experienced in the arcane art of Perl, was confident he could help out.
The Perl script had started out as a quick hack by an in-house developer, and was little more than a simple CGI script that managed the company's website account database. Apparently, it had run "instantly" many months back, but as of late, it was seeing heavy use and taking a few minutes to run. Worse, it was "occasionally" losing data. And by occasionally, I mean most of the time: it'd typically took an a good three or four attempts to create an account or change a password.
The first thing Tom wanted to check on was the database settings. Steve couldn't find any database settings, but it was clearly using some kind of database, as the information was all in associative arrays, and there was no load routine to be found. Steve assumed that it was using a tied hash, to one of the hierarchical databases Perl has had available forever. Hearing it was using something that should be reasonable, Tom next suggested looking for nested loops, and there weren't any of those.
"Um, Tom," Steve said, "What's Data::Dumper?"
"That's a debugging module - it lets you output, in text format, pretty much any Perl data structures, regardless of how complex."
"Well, it looks like there may be some debugging code left in here, then - I see after it's finished with the job, it does a 'print STDERR Data::Dumper([\%hash], [qw(*hash)]);'"
"Wait, didn't you say he used %hash as the database tie?" Tom asked quickly. "That could be why it's so slow right there - he's dumping the entire password database as text after each execution. You have a test environment, right? Comment that out and see what it does."
"Damn it," Steve said, "Somebody else made a change to the test environment script. Oh well, I'm the only one who's supposed to be making changes to this right now, I'll just force my write. It's not the first time someone else has changed this file since I was given full ownership of it. They'll just have to learn they need to talk to me before changing it."
Steve tried the web page again after forcing his save, but the script still took nearly a minute to log him into their test environment server.
Tom asked Steve to look for a few other patterns, but they all turned up empty. Then, just as Tom was about to give up, and say he probably couldn't help over the phone, one of Steve's coworkers exclaimed loud enough for Tom to hear, "Wow! What did you do to the test server? That thing flies! It's refusing my login, but it's doing it so fast!"
Tom said, "Search for 'open.*STDERR'."
Steve found this:
sub init {
($TMPFILE = $0) =~ s#(.*)/(.*)#/$1/.$2.$$/;
open(STDERR, ">$TMPFILE") or die "Cannot save state: $!\n";
open(STDIN, "<$0");
while (<>) {
print STDERR;
last if /sub BEGIN/;
}
}
The script had a single BEGIN block, after all of the rest of the code, and the POD documentation. The BEGIN block contained a single statement:
%hash = ( 'admin' => "83fcb0032cfb59c0327401d4fab13ea7", 'joeb' => "afc7090be5e7b01296850e5436a88872", 'alexp' => "b385c5b6899594b3aa220f34e493ab39", ...snip tens of thousands of lines... );
On the bright side, it didn't take long for Steve to convert the hash into a tied hash.
You'll need to harness the power of rainbows.
Imagination! |
|
While we're throwing blame around, it's often a good idea to blame management.
Upper management at my company is seemingly often wowed by things like pretty pictures and friendly salesmen. Contractors are often friendly salesmen (or have friendly salesmen represent them), and are frequently equipped with pretty pictures. Hence, management chooses developers on criteria which don't accurately reflect the quality of their would-be work. The other reason to blame management is that they too much about getting something done NOW (IE, quick hack), and not enough about getting something done properly. Often times, the lowest bidder says they can hack something together quickly, and they'll get the nod from management. But doing the job properly (from the start and/or revamping existing code) is overlooked because it costs money and doesn't usually feature pretty pictures. The moral of the story (we've found) is to use pretty pictures. DaveE |
|
Eons ago, back in the dial-up BBS days, a freind of mine was writing his own BBS software. After I got his permission to test it's security, I managed to crash the 'gamble time' feature (since there was a limited number of phone lines, user login time was limited, but there was an option to gamble a number of minutes for a 1:3 chance of doubling the number) by gambling a negative number of minutes, hence 'losing' my way to a larger number of minutes, causing an integer overflow.
That dumped me into the basic interpreter, but still redirected over the modem. I found that he had the user/password database appended to the code like "10034 DATA "User", "Password"... I helped him get all those issues fixed up, adding a simple hash to the data; adding a disconnect user and restart on fatal errors, and limiting the input and output of the gambling function. |
| « OUCH! | ISelfAware, Very Thorough, Crazy Hashmaps, and More » |