image provider

Camouflage


The longer it takes for a bug to surface, the harder it is to find.
~ Roedy (1948-02-04 age:70)
Much of the skill in writing unmaintainable code is the art of camouflage, hiding things, or making things appear to be what they are not. Many depend on the fact the compiler is more capable at making fine distinctions than either the human eye or the text editor. Here are some of the best camouflaging techniques.
  1. Write Efficient Code

    We should forget about small efficiencies, say about 97% of the time; premature optimization is the root of all evil.
    ~ Donald Ervin Knuth (1938-01-10 age:80)
    More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason — including blind stupidity.
    ~ W. A. Wulf (1939-12-08 age:78)
    The safest way to disguise your obfuscation work then is to make it look as if your motive for it is making the program run faster.
  2. Code That Masquerades As Comments and Vice Versa

    : Include sections of code that is commented out but at first glance does not appear to be. Without the colour coding, would you notice that three lines of code are commented out?
  3. namespaces

    : Struct/union and typedef struct/union are different name spaces in C (not in C++). Use the same name in both name spaces for structures or unions. Make them, if possible, nearly compatible.
    typedef struct {
    char* pTr;
    size_t lEn;
    } snafu;

    struct snafu {
    unsigned cNt
    char* pTr;
    size_t lEn;
    } A;

  4. Hide Macro Definitions

    : Hide macro definitions in amongst rubbish comments. The programmer will get bored and not finish reading the comments thus never discover the macro. Ensure that the macro replaces what looks like a perfectly legitimate assignment with some bizarre operation, a simple example:
    #define a=b a=0-b
  5. Look Busy

    : use define statements to make made up functions that simply comment out their arguments, e.g.:
    #define fastcopy(x,y,z) /*xyz*/

    fastcopy(array1, array2, size); /* does nothing */
  6. Use Continuation to hide variables

    : Instead of using
    #define local_var xy_z
    break up xy_z onto two lines:
    #define local_var xy\
    _z // local_var OK
    That way a global search for xy_z will come up with nothing for that file. To the C preprocessor, the \ at the end of the line means glue this line to the next one.
  7. Arbitrary Names That Masquerade as Keywords

    : When documenting and you need an arbitrary name to represent a filename use file . Never use an obviously arbitrary name like Charlie.dat or Frodo.txt. In general, in your examples, use arbitrary names that sound as much like reserved keywords as possible. For example, good names for parameters or variables would be: bank, blank, class, const, constant, input, key, keyword, kind, output, parameter parm, system, type, value, var and variable . If you use actual reserved words for your arbitrary names, which would be rejected by your command processor or compiler, so much the better. If you do this well, the users will be hopelessly confused between reserved keywords and arbitrary names in your example, but you can look innocent, claiming you did it to help them associate the appropriate purpose with each variable.
  8. Code Names Must Not Match Screen Names

    : Choose your variable names to have absolutely no relation to the labels used when such variables are displayed on the screen, e. g. on the screen label the field Postal Code but in the code call the associated variable zip.
  9. Don’t Change Names

    : Instead of globally renaming to bring two sections of code into sync, use multiple TYPEDEFs of the same symbol.
  10. How to Hide Forbidden Globals

    : Since global variables are evil, define a structure to hold all the things you’d put in globals. Call it something clever like EverythingYoullEverNeed. Make all functions take a pointer to this structure (call it handle to confuse things more). This gives the impression that you’re not using global variables, you’re accessing everything through a handle. Then declare one statically so that all the code is using the same copy anyway.
  11. Hide Instances With Synonyms

    : Maintenance programmers, in order to see if they’ll be any cascading effects to a change they make, do a global search for the variables named. This can be defeated by this simple expedient of having synonyms, such as
    #define xxx global_var // in file std.h
    #define xy_z xxx // in file ..\other\substd.h
    #define local_var xy_z // in file ..\codestd\inst.h
    These defs should be scattered through different include-files. They are especially effective if the include-files are located in different directories. The other technique is to reuse a name in every scope. The compiler can tell them apart, but a simple minded text searcher cannot. Unfortunately SCIDs in the coming decade will make this simple technique impossible. since the editor understands the scope rules just as well as the compiler.
  12. Long Similar Variable Names

    : Use very long variable names or class names that differ from each other by only one character, or only in upper/lower case. An ideal variable name pair is swimmer and swimner. Exploit the failure of most fonts to clearly discriminate between ilI1| or oO08 with identifier pairs like parselnt and parseInt or D0Calc and DOCalc. l is an exceptionally fine choice for a variable name since it will, to the casual glance, masquerade as the constant 1. In many fonts rn looks like an m. So how about a variable swirnrner. Create variable names that differ from each other only in case e.g. HashTable and Hashtable.
  13. Similar-Sounding Similar-Looking Variable Names

    : Although we have one variable named xy_z, there’s certainly no reason not to have many other variables with similar names, such as xy_Z, xy__z, _xy_z, _xyz, XY_Z, xY_z and Xy_z.

    Variables that resemble others except for capitalization and underlines have the advantage of confounding those who like remembering names by sound or letter-spelling, rather than by exact representations.

  14. Overload and Bewilder

    : In C++, overload library functions by using #define. That way it looks like you are using a familiar library function where in actuality you are using something totally different.
  15. Choosing The Best Overload Operator

    : In C++, overload +,-,*,/ to do things totally unrelated to addition, subtraction etc. After all, if the Stroustroup can use the shift operator to do I/O, why should you not be equally creative? If you overload +, make sure you do it in a way that i = i + 5; has a totally different meaning from i += 5; Here is an example of elevating overloading operator obfuscation to a high art. Overload the '!' operator for a class, but have the overload have nothing to do with inverting or negating. Make it return an integer. Then, in order to get a logical value for it, you must use '! !'. However, this inverts the logic, so [drum roll] you must use '! ! !'. Don’t confuse the ! operator, which returns a boolean 0 or 1, with the ~ bitwise logical negation operator.
  16. Overload new

    : Overload the new operator - much more dangerous than overloading the +-/*. This can cause total havoc if overloaded to do something different from it’s original function (but vital to the object’s function so it’s very difficult to change). This should ensure users trying to create a dynamic instance get really stumped. You can combine this with the case sensitivity trick: also have a member function and variable called New.
  17. #define

    : #define in C++ deserves an entire essay on its own to explore its rich possibilities for obfuscation. Use lower case #define variables so they masquerade as ordinary variables. Never use parameters to your preprocessor functions. Do everything with global #defines. One of the most imaginative uses of the preprocessor I have heard of was requiring five passes through CPP (C++) before the code was ready to compile. Through clever use of defines and ifdefs, a master of obfuscation can make header files declare different things depending on how many times they are included. This becomes especially interesting when one header is included in another header. Here is a particularly devious example:
    #ifndef DONE
    #ifdef TWICE
    // put stuff here to declare 3rd time around
    void g(char* str);
    #define DONE
    #else // TWICE
    #ifdef ONCE
    // put stuff here to declare 2nd time around
    void g(void* str);
    #define TWICE
    #else // ONCE
    // put stuff here to declare 1st time around
    void g(std::string str);
    #define ONCE
    #endif // ONCE
    #endif // TWICE
    #endif // DONE
    This one gets fun when passing g() a char* because a different version of g() will be called depending on how many times the header was included.
  18. Compiler Directives

    : Compiler directives were designed with the express purpose of making the same code behave completely differently. Turn the boolean short-circuiting directive on and off repeatedly and vigourously, as well as the long strings directive.
  19. Red Herrings

    Pepper your code with variables that are never used and methods that are never called. This is most easily done by failing to remove code that is no longer used. You can save the code on grounds someday it may need to be revived. You get bonus points if these drone variables and methods have names similar to actual worker ones. The maintenance programmer will inevitably confuse the two. Changes made to drone code will happily compile, but have no effect.

This page is posted
on the web at:

http://mindprod.com/jgloss/unmaincamouflage.html

Optional Replicator mirror
of mindprod.com
on local hard disk J:

J:\mindprod\jgloss\unmaincamouflage.html
Canadian Mind Products
Please the feedback from other visitors, or your own feedback about the site.
Contact Roedy. Please feel free to link to this page without explicit permission.

IP:[65.110.21.43]
Your face IP:[3.144.104.175]
You are visitor number