• (cs)

    Oh my god. I love C, and this just scared the bejeezus out of me.

    The mere idea of copy-pasting hunks of code to manage each field separately is evil enough.

  • Heikki (unregistered)

    The pattern I use to sidestep the issue is to write the static part of the SQL like this:

    SELECT * FROM foo WHERE 1=1

    After that, you just always put an AND in front of all the dynamic quals. The dummy 1=1 clause will be optimized away by the parser in the database.

    I guess SQL wasn't designed for dynamic machine-generation...

  • nemo (unregistered)

    i feel sick. there are Geneva Conventions against this sort of thing right?

  • Corporate Felon (unregistered)

    Oh god! It Burns! It Burns!

  • (cs)

    Before I discovered adding a 1=1, I wrote some code that wasn't quite as peculiar, but was probably worse than this.

    If was a bunch of nested if-statements. I only put the word "WHERE" in my sql statement if something was selected as criteria so the if-statements kept adding up for every single field.

  • (cs)

    Has anybody mentioned SQL injection yet?

  • blastard (unregistered)

    That is just brillant: sprintf with input string as target..

    captcha: slashbot - kill all bots now before it is too late?

  • Pasa (unregistered)

    And the code is full of undefined behavior -- writing to the buffer that was passed to sprintf as an argument. (btw a pretty widespread WTF :-( )

  • KluZz (unregistered)

    There are a couple nice "Shlemiel the painter's algorithm" there too, the way it keeps re-sprintf'ing the previously sprintf'ed chunk of the query with every iteration of the for loops. In fact, it's done twice for each iteration in the second loop.

  • Vulor (unregistered)

    $sql = "SELECT * FROM table WHERE TRUE "; $sql .= "AND other_stuff";

  • (cs) in reply to danixdefcon5
    danixdefcon5:
    Oh my god. I love C, and this just scared the bejeezus out of me.

    Hey, I love C too, but I wouldn't let just anyone use it, in the same way I wouldn't let just anyone perform an appendicitis. Nor would I use it for this kind of application (if it was really old you might have an excuse). So basically the person or persons responsible should be shot. It's not murder, it's increasing the genetic code base.

  • (cs)
    sprintf( stmt, "%s AND ", stmt );
    Well since he isn't checking the length of the string at any point, wouldn't
    strcat(stmt, " AND ");
    have been a quicker way to overflow the buffer?
  • (cs) in reply to Vulor
    Vulor:
    $sql = "SELECT * FROM table WHERE TRUE "; $sql .= "AND other_stuff";

    Just make sure you handle the case where other_stuff is null. The last thing you want to do is "SELECT * FROM table WHERE TRUE"

    /I was an intern once upon a time...

  • (cs)

    <pedantic>It's bonus not bouns!!</pedantic>

    That was a steaming pile of code, if I had to deal with that... I.. will.. KILL THE BASTARD THAT WROTE IT!!

  • Pasotman (unregistered) in reply to TheJasper

    You obviously mean an appendectomy...

  • (cs) in reply to TheJasper
    TheJasper:
    danixdefcon5:
    Oh my god. I love C, and this just scared the bejeezus out of me.

    Hey, I love C too, but I wouldn't let just anyone use it, in the same way I wouldn't let just anyone perform an appendicitis. Nor would I use it for this kind of application (if it was really old you might have an excuse). So basically the person or persons responsible should be shot. It's not murder, it's increasing the genetic code base.

    Hardly increasing the code base -- more a sort of Darwinian eager optimization...

    BTW, is it more intensely painful to "perform an appendicitis" or to maintain code like this?

    Oh good, the bar opens in half an hour. Time for a general anaesthetic.

  • (cs)

    The goggles! They do nothing!

  • One Time (unregistered) in reply to TheJasper
    TheJasper:
    Hey, I love C too, but I wouldn't let just anyone use it, in the same way I wouldn't let just anyone perform an appendicitis.

    Ignoring the obvious difficulty one would face in attempting to perform a medical condition, I don't think that I would allow anyone to perform an appendicitis. That said, if someone did find a way to do so, I would only allow a qualified surgeon to perform an appendectomy to resolve it.

    CAPTCHA: muhahaha

  • (cs)

    Maybe I'm missing something, but what's the need for "WHERE 1=1"? Doesn't C have a strlen or trim function? If so, just build everything -after- the WHERE Then, once that's been built, check its length and if it has any length at all, add WHERE to the query, and add the built expression.

  • Beavis (unregistered)

    Pfft. It's not a real WTF unless your web app written in C also uses Oracle Pro*C!

    I'm going to go vomit now...oh, the memories...

  • (cs) in reply to vertagano
    vertagano:
    Maybe I'm missing something, but what's the need for "WHERE 1=1"? Doesn't C have a strlen or trim function? If so, just build everything -after- the WHERE Then, once that's been built, check its length and if it has any length at all, add WHERE to the query, and add the built expression.
    That would be the proper way to do it, but I think most folks are just extrapolating the wtf code from the submission.
  • Hallvard (unregistered)

    Another variant: char *delim = ""; For each field: sprintf(..., delim, ...); delim = " and ";

    Now, let's guess if their GetField() handles SQL characters like quote specially, or if the web user can send a quote followed by some SQL stuff...

  • Rick (unregistered) in reply to vertagano
    vertagano:
    Maybe I'm missing something, but what's the need for "WHERE 1=1"? Doesn't C have a strlen or trim function? If so, just build everything -after- the WHERE Then, once that's been built, check its length and if it has any length at all, add WHERE to the query, and add the built expression.

    No, the issue is whether or not to put an AND before each condition.

    select * from table where a=1 and b=2 and c=3

    The first condition "a=1" does not have an AND before it, but the rest do. So what some people are recommending is to have

    select * from table where 1=1 and a=1 and b=2 and c=3

    That way every condition you might have based on the form fields has an AND before it.

  • (cs) in reply to Rick
    Rick:
    No, the issue is whether or not to put an AND before each condition.

    select * from table where a=1 and b=2 and c=3

    The first condition "a=1" does not have an AND before it, but the rest do. So what some people are recommending is to have

    select * from table where 1=1 and a=1 and b=2 and c=3

    That way every condition you might have based on the form fields has an AND before it.

    Alright, so amend what I said slightly. Always add an " AND " -after- each element when building the expression. Then at the end, when checking the length of built expression, if it has any length, simply remove the last " AND " (by taking the length, subtracting the constant length of " AND " and changing that first space to a '\0' character.) Of course, there is a good question about SQL security here--I wonder what steps have been taken to sanitize the input.

  • Ant (unregistered)

    Another variant...

    $query = 'select * from table where'; $query_x = ''; foreach ($fields as $k => $v) { if ($query_x) $query_x.= ' and'; $query_x.= " $k = '$v'"; } $query.= $query_x;

    I guess it's not a good as the 'where true' trick, but anything has to be better than that C snippet... <shivers>

  • JL (unregistered) in reply to Hallvard
    Hallvard:
    Another variant: char *delim = ""; For each field: sprintf(..., delim, ...); delim = " and ";
    That's a nice solution -- much more clear and probably just as efficient. I wouldn't have thought of it, myself; I guess I've been spoiled by Python's and .NET's "join" function for strings.
  • (cs) in reply to vertagano
    vertagano:
    Rick:
    No, the issue is whether or not to put an AND before each condition.

    select * from table where a=1 and b=2 and c=3

    The first condition "a=1" does not have an AND before it, but the rest do. So what some people are recommending is to have

    select * from table where 1=1 and a=1 and b=2 and c=3

    That way every condition you might have based on the form fields has an AND before it.

    Alright, so amend what I said slightly. Always add an " AND " -after- each element when building the expression. Then at the end, when checking the length of built expression, if it has any length, simply remove the last " AND " (by taking the length, subtracting the constant length of " AND " and changing that first space to a '\0' character.) Of course, there is a good question about SQL security here--I wonder what steps have been taken to sanitize the input.

    Yes of course you can do that, but think about the possibility of error prone trimming etc. If you simply started with 1=1 or simply True, there is no code gymnastics to go through, it has no impact on the query speed, and is easily readable. With all that I would say using 1=1 makes the code maintainable by even a junior developer.

  • PS (unregistered)

    So many good WTF's lately. Not all in languages I know but it's no different than taking a vacation in Europe. You can't understand a thing that is being said but you know that it is a load of crap anyway.

  • faranim (unregistered) in reply to vertagano
    vertagano:
    Maybe I'm missing something, but what's the need for "WHERE 1=1"? Doesn't C have a strlen or trim function? If so, just build everything -after- the WHERE Then, once that's been built, check its length and if it has any length at all, add WHERE to the query, and add the built expression.

    The point is that you want to code to be easily readable. If you build everything -after- the WHERE clause like you say, you need to add extra (WTFish) logic so you don't end up with:

    SELECT * FROM MyTable WHERE AND "first_name" = 'bob';

    The easier approach is to start with:

    SELECT * FROM MyTable WHERE TRUE (or, WHERE 1=1)

    and then for every additional condition just append " AND condition" to the SQL string.

    Other approaches require the use of some sort of "and" variable (like this WTF code), so you don't end up creating a "WHERE AND condition" SQL statement.

  • (cs)

    The worst (meaning, best) CodeSOD that has been published in a while... The real WTF is that it's not using AJAX.

  • Unomi (unregistered)

    Maybe I'm a dork but at least in PHP you have the implode function:

    $fields = array(); $fields[] = 'field1 = '.$value; $fields[] = 'field2 = '.$value; $fields[] = 'field3 = '.$value;

    $fields = implode(' and ',$fields);

    I don't know if C has some function similar to implode? If not, they should look into the PHP source to look how it is done. Because that is written in C too....

    Captcha: yummy (yes, having some pizza tonight)

    • Unomi -
  • sol (unregistered)

    PERL hold the everything in this universe togethor like crazy glue ;)

    PHP is PERL's less sticky cousin and ColdFusion is according to Jim Carlow the most powerful tool known to man... what do I know though I get paid to write vb code all day...

  • Jonno (unregistered) in reply to MaGnA
    MaGnA:
    The worst (meaning, best) CodeSOD that has been published in a while... The real WTF is that it's not using AJAX.
    That made me laugh. :)

    This site makes me very, very glad that I don't maintain code for a living (well, other people's at least!)

  • StressBomb (unregistered)

    Some people are amazed that this site has multiple "WTF"-s every day that show terrible coding...

    But my personal entertainment are the replies by "know it all" programmers which openly describe their just as funny techniques for dealing with a certain problem.

    WHERE 1=1 AND, WHERE TRUE AND... guys what is wrong with you? Sure the SQL will optimize it away, does that means throw in random statements in your SQL?

    It's so simple to do it properly (pseudo code, so pardon for not using string builder, just illustrating a point):

    string query = '';

    for (int i = 0, max < statements.length - 1; i < max; i++) { query = statement[i] + ' AND '; } query += statements[max];


    In PHP I also often do it simply like this:

    $query = implode(' AND ', $statements);

    ... which will automatically build the correct string for me.

  • StressBomb (unregistered) in reply to StressBomb

    Pardon for the typo: "max < statements.length - 1". The "<" should of course be "=".

  • (cs)

    Mhmmm... makes me wonder what happened to the web apps I've written in C 9 years ago... are they still in use?

    Anyway, this "counter" approach is obviously retarded. In most cases, there is at least one where condition that is always required (like "... where active_flag='1'), so it's very easy to handle it. If not, just repeatedly add condition+" and " to the statement and strip the last " and " at the end; resp., it there is no such " and ", strip the where. Very tricky people might add condition+

    "   and "
    , so they can just strip the last 6 characters

    query[strlen(query)-6]='\0';

  • Phat Wednesday (unregistered)

    Why no vitriol for what a crappy language C is?

    Isn't it obvious from previous VB posts that it's the language's fault for WTFery?

    Here, I'll get everyone started with a paraphrase from a previous thread:

    "I wish they would have made [C] a little bit harder to learn, to keep away the stupid people. Or at least make it not a viable language to use for production-level programming!"

    Oh yeah, and what's with all those semicolons? If I had to figure out what lines they go after and what lines they don't I'd lose IQ points and get carpel tunnel in my right pinky!

  • (cs) in reply to Phat Wednesday

    O-oh say can you "C"?

  • (cs) in reply to StressBomb
    StressBomb:
    Some people are amazed that this site has multiple "WTF"-s every day that show terrible coding...

    But my personal entertainment are the replies by "know it all" programmers which openly describe their just as funny techniques for dealing with a certain problem.

    WHERE 1=1 AND, WHERE TRUE AND... guys what is wrong with you? Sure the SQL will optimize it away, does that means throw in random statements in your SQL?

    It's so simple to do it properly (pseudo code, so pardon for not using string builder, just illustrating a point):

    string query = '';

    for (int i = 0, max < statements.length - 1; i < max; i++) { query = statement[i] + ' AND '; } query += statements[max];


    In PHP I also often do it simply like this:

    $query = implode(' AND ', $statements);

    ... which will automatically build the correct string for me.

    Here is where I feel you fall apart:

    Select Field from Table

    Now lets say you have no statements to add, you are fine. But lets say you have one to add, you get the following:

    Select Field from Table Field = value

    Obviously, not right, where is your WHERE? If you instead presume the where exists and you have no statements to add you have the following:

    Select Field from Table Where

    Which is also wrong. Using a dummy salting you get a valid query every time without adding complexity to code. Even your implodes don't handle the adding of the where clause when needed unless you "count" your parameters in some way.

  • (cs) in reply to Jonno
    Jonno:
    This site makes me very, very glad that I don't maintain code for a living (well, other people's at least!)

    The idea that someone who doesn't have to face this kind of stuff as part of his daily job, would still enjoy reading this site so as to take pleasure in the tortures that the rest of have to deal with, is kind of scary.

  • (cs) in reply to Licky Lindsay

    Oh wow, first time I have seen this.

    A whole group of posts talking about how C is the problem rather than the programmer just got removed, albeit on topic.

    How far are we going to be censured here?

  • Evo (unregistered)

    Hmmm some mentioned the SQL injection... But what about the probable buffer overflow?

  • James (unregistered)

    What you don't know:

    The original developer of the site was told that the code had to be more maintainable than Brainfuck or Whitespace; they just didn't say how much more maintainable.

    In all seriousness, though, I feel like using a 40k-line monolithic source file (and the leaking memory with every query) is a much bigger WTF than chosing a somewhat-inefficient way of building a query. I can do you one worse on that front: I got tapped to fix an app (that had made it into production!!!) where the SQL query returned the whole table, then the JSP used straight embedded Java code to pick the appropriate rows to return. They didn't see a need to implement dynamic SQL queries, because they had tested it with a few dozen rows in the table and it performed just fine. Of course, when there wound up being several thousand records after it was deployed, pages took a surprisingly long time to load... so, as you can see, it could be worse ;-)

  • (cs) in reply to TheJasper
    TheJasper:
    Hey, I love C too, but I wouldn't let just anyone use it ... So basically the person or persons responsible should be shot.
    If it makes you feel any better, the original developer and his wife (a former contractor for the company) were sued on an unrelated technicality because of this project.
  • Phat Wednesday (unregistered) in reply to StressBomb
    StressBomb:
    Some people are amazed that this site has multiple "WTF"-s every day that show terrible coding...

    But my personal entertainment are the replies by "know it all" programmers which openly describe their just as funny techniques for dealing with a certain problem.

    WHERE 1=1 AND, WHERE TRUE AND... guys what is wrong with you? Sure the SQL will optimize it away, does that means throw in random statements in your SQL?

    It's so simple to do it properly (pseudo code, so pardon for not using string builder, just illustrating a point):

    string query = '';

    for (int i = 0, max < statements.length - 1; i < max; i++) { query = statement[i] + ' AND '; } query += statements[max];

    [snip]

    Yes, it's possible to create a where clause builder but as the previous poster points out there are a few gotchas with it.

    What's bad about your example is the maintenance burden placed on others to have to read and understand your parsing routines, then decide if it's important to the work they're doing. 1=1 is a simple and direct solution to the problem that can be read and understood quickly. A singleline comment will clarify its use to anyone reading the code.

    Applicable Rules: #2 Rule of Clarity: Clarity is better than cleverness #5 Rule of Simplicity: Design for Simplicity; add complexity only where necessary. #7 Rule of Transparency: Design for visibility to make inspection and debugging easier.

  • (cs)

    The WTF element I'm surprised nobody has questioned is the variable name. I know C uses "&" instead of "and" as a boolean operator, but would it hurt to have named the variable something like "UseAnd"?

    I keep imagining the effects of and++. Is and++ == or? Would and-- == NAND? Or perhaps it's a fuzzy logic thing:

    11111111 and-- 11111110 == TRUE // it's almost and.
    00110011 and++ 00110011 == FALSE // needs more andbell

    For what it's worth, I use the "delete the trailing AND" method described above when building dynamic SQL. I don't think the number of clock cycles lost to string manipulation is going to be terribly significant.

  • (cs)

    I would rather eat dryer lint than maintain this pile of steaming poo.

  • Paul (unregistered)

    I'll admit, I'm the submitter on this one.

    Some things were lost in the translation as it was scrubbed and spiffed up for presentation here.

    First of all, it already had a default WHERE clause by virtue of a join (this being Oracle [which was attacked with Pro*C] the join condition was being enforced thus).

    Even the non-dynamic queries were written using this same kind of formatting paradigm:

    SELECT ... WHERE ... AND CONDITION AND OTHER_CONDITION AND ...

    The coder had picked up the bad practice and made it ubiquitous to the dynamic construction.

    And I had this monster for 8 months of minor tweaks while I was petitioning the opportunity to do a rewrite, not the 3 weeks it was somehow boiled down to.

    [evil corporate name redacted] is still using this, the B2C website it was derived from, and many of the same internal controls that were the illegitimate children of both. Until I got there, they weren't even using any consistent versioning controls, developers were rolling to production, and the poor NOC and DBAs were constantly being paged for things that really weren't their fault.

    I left it all behind last May after 2 1/2 years, and haven't been sorry once.

    Oh, and when we upgraded versions of GCC, it suddenly considered 'and' a reserved word, and the variable name had to be changed.

  • Duston (unregistered)

    Sounds like a cool name for a medival re-enactor. "All hail, the Counter of And!"

  • (cs)
    powered by back-end applications; which is to say, powered by evil.
    Jim Morrison, the ol' back door man himself, and I agree: back-end applications are not evil.

Leave a comment on “The Counter of And”

Log In or post as a guest

Replying to comment #125338:

« Return to Article