* The program was centered around a single core library. This library worked by loading several component libraries and then providing wrappers around them. The way the wrappers worked was a bit convoluted, but this was probably the least bad part of it.
* The largest component library involved creating an object and then calling its methods. Rather than implementing this directly, it was done in this bizarrely convoluted way where an object would be created and then a pointer would be put in a small, fixed-size array. The function then returned an index into that array. All the methods would then work on that index instead of the pointer directly. Some methods checked the bounds, while others didn't. If the array filled up, the program would crash.
* There was a static mapping of strings that was used as a lookup table. The table was indexed by the first two letters in each entry. Every time a value in the table was looked up, it would search through all the index prefixes until it found the matching one. It would then search through every entry in the table with that prefix. It would stop if either the entry matched, or the prefix changed. There was no boundschecking whatsoever. If the key contained a prefix not in the index, it would crash. If the key was not in the index and the prefix was the last prefix, it would wait for the prefix in the table to change, going past the end and crashing. The cherry on top was that everything was already completely lexicographically sorted, so they could have just used bsearch without having to change anything else. Oh and this was not a small amount of data in a minor part of the program, it was 5MB+ of data with 100,000+ entries that was regularly called from a loop that runs thousands of times.
* In the biggest component, nearly everything was stored in one enormous class. And I mean enormous. It was dozens of megabytes in size and had hundreds of fields. Nearly every other class and struct was embedded in it, directly without a pointer. Well actually there were some pointers but that part was even more absurd. The class contained pointers to various objects, but those objects were already in the class - but sometimes they weren't. There was a whole bunch of spaghetti code to check whether they were in the class directly, or whether the pointers pointed to classes that were allocated in the heap, or if they were null. All of this seemingly served no purpose whatsoever.
* There was a function that took a c-string of a directory path and added another c-string containing a filename. Rather than just using a malloc and strcat, it did the following: create an std::vector; parse the directory path splitting each '/', converting it to wide-character string and then appending it to the vector; convert the file name to a wstring and appended it too; create a new wstring and then append each element of the array followed by a '/'; convert the wstring back to a c-string. I'm not kidding.
This was just the tip of the iceberg.