News





Error'd: Legitimate Links;

"Swedish...Russian...English....same difference!" wrote Fred.

 

Scott P. writes, "I had 6 right and 5 wrong on this online quiz, but apparently I did better than that, getting '10 out of correct'."

 

"I had to accept information while trying to modify a booking through the official Iberia Airlines app," Mario writes.

 

Ben S. wrote, "YouTube would like to... umm... do a sorta complicated thing, is that OK?

 

"So, do I follow the text box or do I follow the suggestion?" writes Chuk G.

 

Adam S. writes, "Do I smoke? ...Maybe?"

 

[Advertisement] Infrastructure as Code built from the start with first-class Windows functionality and an intuitive, visual user interface. Download Otter today!


CodeSOD: Abstract Test Case;

A great many breakfast cereals promise some sort of health benefit. This brand is good for your heart, that brand has 11 essential vitamins and minerals. This one’s got bran! Just because there’s a promise of health benefits doesn’t mean they actually exist- most of these cereals are lightly fluffed sugar held together with a smidge of starch.

Object-oriented languages promise a lot of code-health benefits, and used properly, they can certainly deliver. In this somewhat tortured metaphor, the Lucky Charms marshmallow of OO features is Inheritance. It’s tasty, it’s easy to explain, but it’s not really good for your code. A little bit, here-and-there, from time-to-time is great. But some folks buy the three pound bag and that’s just not good for anybody.

Daniel took over some code left behind by a retiring co-worker. The code was seeded through with abstract classes- though, because this was Python, “abstract” was more of a convention than a statement of fact. This predecessor took abstraction to its “logical” conclusion, and when testing abstract classes, they wrote abstract tests:

class TestAbstractDriver(unittest.TestCase):

    """Test case docstring."""

    def test_name(self):
        pass # for those not familiar with Python,
            # "pass" is how you write a method with no implementation

This code was followed by AbstractDriverTest, which inherited from TestAbstractDriver and actually implemented the test.

[Advertisement] Universal Package Manager – store all your Maven, NuGet, Chocolatey, npm, Bower, TFS, TeamCity, Jenkins packages in one central location. Learn more today!


The Official Software;

At the very beginning of my career, I was a junior programmer on a team that developed software to control an electronics test station, used to diagnose problems with assorted components of jet fighters. Part of my job was the requisite grunt work of doing the build, which entailed a compile-script, and the very manual procedure of putting all the necessary stuff onto a boot-loader tape to be used to build the 24 inch distribution disk arrays.

An unspooled magnetic tape for data storagesource

This procedure ran painfully slowly; it took about 11 hours to dump a little more than 2 MB from the tape onto the target disk, and nobody could tell me why. All they knew was that the official software had to be used to load the bootstrap routine, and then the file dumps.

After killing 11 hour days with the machine for several months, I had had it; I didn't get my MS to babysit some machine. I tracked down the source to the boot loader software, learned the assembly language in which it was written and slogged through it to find the problem.

The cause was that it was checking for 13 devices that could theoretically be hooked up to the system, only one of which could actually be plugged in at any given time. The remaining checks simply timed out. Compounding that was the code that copied the files from the tape to the disk. It was your basic poorly written file copy routine that we all learn not to do in CS-102:

    // pseudo code
    for each byte in the file
        read next byte from tape
        write one byte to disk
        flush

Naturally, this made for lots of unnecessary platter-rotation; even at over 3,000 RPM, it took many hours to copy a couple MB from tape to the disk.

I took a copy of the source, changed the device scanning routine to always scan for the device we used first, and skip the others, and do a much more efficient full-buffer-at-a-time data write. This shortened the procedure to a very tolerable few minutes. The correctness was verified by building one disk using each boot loader and comparing them, bit by bit.

Officially, I was not allowed to use this tape because it wasn't sanctioned software, but my boss looked the other way because it saved a lot of time.

This worked without a hitch for two years, until my boss left the company and another guy was put in charge of my team.

The first thing he did was confiscate and delete my version of the software, insisting that we use only the official version. At that time, our first kid was ready to arrive, and I really didn't want to stay several hours late twice a week for no good reason. Given the choice of helping take care of my wife/kid or babysitting an artificially slow process, I chose to change jobs.

That manager forced the next guy to use the official software for the next seven years, until the company went out of business.

[Advertisement] Release! is a light card game about software and the people who make it. Play with 2-5 people, or up to 10 with two copies - only $9.95 shipped!


CodeSOD: Too Salty;

The first rule of building your own password storage mechanisms is don’t. Like most other highly-specialized wheels, you aren’t going to do as good a job as someone who specializes in it. It’s bad enough when you write your own date mangling code, but for security-critical features, like passwords or encryption, you’re begging for trouble.

Joni spotted some trouble: many of the users in the database had the same password hash. This, of course, should never happen- the password should be combined with a user-specific salt as part of the hashing, so that even if two users had the same password, they’d have different hashes.

Joni investigated, and found the code used:

string EncodePassword(string pass, int passwordFormat, string salt)
{
    if (passwordFormat == 0) // MembershipPasswordFormat.Clear
        return pass;

    //byte[] bIn = Encoding.Unicode.GetBytes(pass);
    byte[] bIn = UTF8Encoding.UTF8.GetBytes(pass);
    byte[] bSalt = Convert.FromBase64String(salt);
    byte[] bAll = new byte[bSalt.Length + bIn.Length];
    byte[] bRet = null;

    Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
    Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
    if (passwordFormat == 1)
    { // MembershipPasswordFormat.Hashed
        HashAlgorithm s = HashAlgorithm.Create(Membership.HashAlgorithmType);
        //bRet = s.ComputeHash(bAll);
        bRet = s.ComputeHash(bIn);
    }
    else
    {
        bRet = EncryptPassword(bAll);
    }

    return Convert.ToBase64String(bRet);
}

Note the Buffer.BlockCopy lines. As you can see, the code does all the important heavy-lifting to prepend the salt to the password… and then it ignores that work and just stores the hash of bIn- the original password as a byte array. There is also a hint, from the comments, that they avoided using clearly-named enums and instead used integers… but kept the enums in the comments, for readability!

TRWTF is that this is the initial commit of this code into source control, so there’s no explanation for this.

[Advertisement] Infrastructure as Code built from the start with first-class Windows functionality and an intuitive, visual user interface. Download Otter today!


CodeSOD: RAM On Through;

The company Tomasz worked for launched a new device line with more RAM than the previous generation. This was supposed to put an end to the sort of memory shortages common to embedded systems. However, it wasn't long before they began hearing from clients whose systems crashed whenever they attempted to upgrade the accompanying software package.

The initial reports were met with surprise and skepticism, but the investigation soon led Tomasz and his cohorts to—you guessed it—a reproducible out-of-memory error.

With RAM not an issue, they took a deeper look at the upgrade process itself. The 50MB upgrade package was supposed to be copied to a special directory so the OS could install it. In C++ on linux, this is a simple task. You could use splice() on a newer linux kernel, or sendfile() on an older one. You could also read and write one buffer at a time. Inefficient, but effective.

As you may already suspect, the developers who'd written the library for handling upgrades had taken a more brillant approach, shown below. readFile() stores the entire file in a string in memory, and writeFile() places it in the desired directory. With this implementation, any device could be brought to its knees with a large-enough upgrade file.

bool readFile(const char *filename, std::string &result)
{
    result.clear();
    FILE *fp=fopen(filename,"rb");

    if (!fp)
    {
        return false;
    }

    const size_t buff_size = 4 * 1024;
    char * buffer = (char *) malloc(buff_size);
    if (!buffer)
    {
        fclose(fp);
        return false;
    }

    size_t r = 0;
    do
    {
        r=fread(buffer,1,buff_size,fp);
        result.append(buffer,buffer+r);
    }
    while(r==buff_size);

    free(buffer);
    fclose(fp);

    return true;
}

bool writeFile(const char *file, const std::string & data )
{
    if(!file) return false;
    FILE *fp=fopen(file,"wb");
    if(!fp) return false;

    fwrite( data.c_str(), sizeof( char ), data.size(), fp );

    int r=ferror(fp);
    fclose(fp);
    return (r==0);
}
[Advertisement] Manage IT infrastructure as code across all environments with Puppet. Puppet Enterprise now offers more control and insight, with role-based access control, activity logging and all-new Puppet Apps. Start your free trial today!


Error'd: Nothing Ventured, Nothing Gained;

"After trying to close my steam support ticket, I got this," writes Joe, "Now, I'm not entirely sure."

 

Hiram P. wrote, "Oh man, listening to Artists 0, 1, and 2 really take me back!"

 

"I was on the ASME.org login page where I guess I'll start over, but wait! it's an endless loop!" wrote John A.

 

Cozzolino writes, "Great, Trenitalia.com now provides puzzles to fill your time while waiting to get onto the train."

 

"The deal sure is tempting but I don't think my closet would be able to handle it," writes Geoff.

 

"Granted, I'm fluent in languages 127, 118, and 93," writes Derek W., "In the end, I just crossed my fingers and went with Autodetect."

 

[Advertisement] Manage IT infrastructure as code across all environments with Puppet. Puppet Enterprise now offers more control and insight, with role-based access control, activity logging and all-new Puppet Apps. Start your free trial today!


Representative Line: Refactoring the Conditional;

Virginia N was trying to refactor some code, and that meant understanding where the value m_PSOC_SIG was used, and why. So, she did some searching, and found this line, which doesn’t contain our value:

ChangePosition("P",true,(bool)ar[6],(DateTime)ar[1],(DateTime)ar[5]);

Now, you might be asking yourself, “what’s the problem?”

Well, let’s put this into a little context. You’re probably familiar with the “do the same thing on both branches” if statement, like this:

        if (m_ProgEnt.SAFF_SIG==m_PSOC_SIG)
        {
                ChangePosition("P",true,(bool)ar[6],(DateTime)ar[1],(DateTime)ar[5]);
        }
        else
        {
                ChangePosition("P",true,(bool)ar[6], (DateTime)ar[1], (DateTime)ar[5]);
        }

Now, that’s annoying, but it’s not a full-on WTF. It’s the sort of thing that probably just accrues in old code-bases, the gradual decay of good- well, not godawful- code into bad by changing requirements and rushed timelines. Once upon a time, the branches probably were different. But neither of those are the line I posted above. Here’s the full code in context:

if (m_ProgEnt!=null)
{
        if (m_ProgEnt.SAFF_SIG==m_PSOC_SIG)
        {
                ChangePosition("P",true,(bool)ar[6],(DateTime)ar[1],(DateTime)ar[5]);
        }
        else
        {
                ChangePosition("P",true,(bool)ar[6], (DateTime)ar[1], (DateTime)ar[5]);
        }
}
else
{

}
ChangePosition("P",true,(bool)ar[6],(DateTime)ar[1],(DateTime)ar[5]);

Virginia removed the conditionals.

[Advertisement] Release! is a light card game about software and the people who make it. Play with 2-5 people, or up to 10 with two copies - only $9.95 shipped!