-Поиск по дневнику

Поиск сообщений в rss_thedaily_wtf

 -Подписка по e-mail

 

 -Постоянные читатели

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 06.04.2008
Записей:
Комментариев:
Написано: 0

The Daily WTF





Curious Perversions in Information Technology


Добавить любой RSS - источник (включая журнал LiveJournal) в свою ленту друзей вы можете на странице синдикации.

Исходная информация - http://thedailywtf.com/.
Данный дневник сформирован из открытого RSS-источника по адресу http://syndication.thedailywtf.com/thedailywtf, и дополняется в соответствии с дополнением данного источника. Он может не соответствовать содержимому оригинальной страницы. Трансляция создана автоматически по запросу читателей этой RSS ленты.
По всем вопросам о работе данного сервиса обращаться со страницы контактной информации.

[Обновить трансляцию]

CodeSOD: Virtually Careful

Вторник, 05 Марта 2019 г. 14:30 + в цитатник

Inheritance is one of those object-oriented features whose importance is perhaps overstated. When I was first being introduced to OO, it was a lot of “code reuse!” and “polymorphism!” and “code reuse!” In practice, inheritance is usually a way to tightly couple two different classes and create more headaches and rework in the future.

That’s why many OO languages favor interfaces, and why the classic Gang-of-Four patterns emphasize the importance of composition in many situations. And, because inheritance can make things complicated, most languages also require single parent inheritance.

Most languages. C++, on the other hand, doesn’t. In C++, I could define a class Car, a class Truck, and then do this:

class ElCamino : Car, Truck {}

As you can imagine, this introduces all sorts of problems. What if both Car and Truck have a method with the same signature? Or worse, what happens if they have the same ancestor class, MotorVehicle? If MotorVehicle defines drive(), and Car and Truck both inherit drive(), where does ElCamino get its drive() function from?

This scenario is known as the Diamond Problem. And C++ offers a simple solution to the Diamond Problem: virtual inheritance.

If, for example, our classes are defined thus:

class Car : virtual MotorVehicle {};
class Truck : virtual MotorVehicle {};
class ElCamino : Car, Truck {};

ElCamino will inherit drive() directly from MotorVehicle, even though both its ancestors also inherited from MotorVehicle. An ElCamino is both a Car and a Truck, but is only a MotorVehicle once, not twice, so anything it inherits from MotorVehicle should only be in the class once.

Now, in practice, multiple-inheritance is one of those luxury foot-guns which allows you to blow off your own foot using anything that implements the shoot() method at the same time. It does have uses, but seeing it used is a bit of a code smell.

Mindy found some code which doesn’t use multiple inheritance. Nowhere in their codebase is there a single instance of multiple inheritance. But her co-worker wants to future-proof against it, or maybe just doesn’t understand what virtual inheritance is, so they’ve manually gone through the codebase and made every child class inherit virtually.

This hasn’t broken anything, but it’s lead to some dumb results, like this:

class SomeSpecificDerivedClass final : public virtual SomeBaseClass
{
   /* ... code ... */ 
};

The key note here is that our derived class is marked as final, so no one is ever going to inherit from it. Ever. It’s sort of a belts and braces approach, except you’re wearing a dress.

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!

https://thedailywtf.com/articles/virtually-careful


Метки:  

CodeSOD: For Each Parallel

Понедельник, 04 Марта 2019 г. 14:30 + в цитатник

Parallel programming is hard. For all the advancements and tweaks we've made to our abstractions, for all the extra cores we've shoved into every CPU, deep down, software still carries the bias of the old uni-tasking model.

Aleksei P works on a software package that is heavily parallel. As such, when interviewing, he talks to candidates about their experience with .NET's Task objects and the async/await keywords.

One candidate practically exploded with enthusiasm when asked. "I've just finshed a pretty large text processing project that reads a text file in parallel!" They whipped out a laptop, pulled up the code, and proudly showed it to Aleksei (and gave Aleksei a link to their repo for bonus points).

public async Taskstring, int>> ParseTextAsync(string filePath, ParamSortDic dic) { if (string.IsNullOrEmpty(filePath)) { throw new ArgumentNullException(nameof(filePath)); } if (Path.GetExtension(filePath)!=".txt") { throw new ArgumentException("Invalid filetype"); } Dictionarystring, int>, IOrderedEnumerablestring, int>>>> sorting = new Dictionarystring, int>, IOrderedEnumerablestring, int>>>> { {ParamSortDic.KeyAsc,word=> word.OrderBy(ws=>ws.Key)}, {ParamSortDic.KeyDesc,word=>word.OrderByDescending(ws=>ws.Key)}, {ParamSortDic.ValueAsc,word=>word.OrderBy(ws=>ws.Value)}, {ParamSortDic.ValueDesc,word=>word.OrderByDescending(ws=>ws.Value)}, }; var wordCount = new Dictionary<string, int>(); object lockObject = new object(); using (var fileStream = File.Open(filePath, FileMode.Open, FileAccess.Read)) { using (var streamReader = new StreamReader(fileStream)) { string line; while ((line = await streamReader.ReadLineAsync()) != null) { var lineModifyLower = Regex .Replace(line, "[^а-яА-я \\dictionary]", "") .ToLower(); var words = lineModifyLower .Split(Separators, StringSplitOptions.RemoveEmptyEntries) .Where(ws => ws.Length >= 4); Parallel.ForEach(words, word => { lock (lockObject) { if (wordCount.ContainsKey(word)) { wordCount[word] = wordCount[word] + 1; } else { wordCount.Add(word, 1); } } }); } } } return sorting[dic](wordCount).ToDictionary(k => k.Key, k => k.Value); }

There's so much to dislike about this code. Most of it is little stuff- it's painfully nested, I don't like methods which process file data also being the methods which manage file handles. Generics which look like this: Dictionary, IOrderedEnumerable>>> are downright offensive.

But all of that's little stuff, in the broader context here. You'll note that the file is read using ReadLineAsync, which is asynchronous. Of course, we await the results of that method in the same line we call it. await is a blocking operation, so… not asynchronous at all.

Of course, that's a trend with this block of code. Note that the words on each line are processed in a Parallel.ForEach. And the body of that ForEach starts by creating a lock, guaranteeing that only one thread is ever going to enter that block at the same time.

Suffice to say, Aleksei didn't recommend that candidate.

[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

https://thedailywtf.com/articles/for-each-parallel


Метки:  

Error'd: Musical Beverages

Пятница, 01 Марта 2019 г. 14:30 + в цитатник

"If the screen is to be believed...This beer is going to rock!" wrote Tim F.

 

Dru writes, "Wait...Mad Libs? No wonder credit card terms are so confusing!"

 

"After selecting a file to open this gem popped up. I think the dialog is as confused as I am," writes Lincoln K.

 

Jan writes, "Yes, speaking of sensitive data, Firefox is asking if I'd like to store the following, possibly sensitive, data!"

 

"Seeing how long it'll take to delete this 30GB VirtualBox snapshot, I'm going to find some way to keep myself busy for the next 40 years," Christian F. writes.

 

Anthony E. wrote, "Maybe by next century, AVG will have worked out how to build an effective anti-virus product?"

 

[Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!

https://thedailywtf.com/articles/musical-beverages


Метки:  

Calculated Security

Четверг, 28 Февраля 2019 г. 14:30 + в цитатник

Carl C spent some time in the late 1980's at a software firm that developed avionics and global positioning systems for military and civilian customers. In their employ, he frequently visited Schlockdeed Corp, a customer with a contract to develop a new generation of jet fighters for the US military. Due to the top secret nature of their work, security was a big deal there.

Whenever Carl entered or left the facility, he had to pass through the security office to get clearance. They would thoroughly inspect his briefcase, jacket, lunchbox, and just about everything short of a full cavity search. Despite the meticulous nature of daily inspections at Schlockdeed, some of their "security measures" bordered on the absurd.

During this era of Sneakernet-type transfers of information, it wasn't uncommon for a programmer to take a box full of floppy disks to and from work every day. Schlockdeed had a rather lax policy regarding disk transportation even though it would be a super easy way to steal their secrets. Subcontractors like Carl would be issued a "media pass" after passing the initial background check to work with Schlockdeed. It was a card that allowed them to carry any number of floppy disks in and out of the building without question.

Carl's tenure was uneventful until he decided to bring his beloved HP-41CX calculator to the office. They were working on some complex algorithms and drawing up equations on a chalkboard was taking too long, so Carl hoped to speed up the process. During his morning inspection, Bill the security guy pulled out the HP-41CX and immediately had a concerned look come over his face.

Bill reached for the radio on his shoulder, "Paulie, we're going to need you. We have a situation." Carl became extremely confused. Had the 41CX been known to be used in bombs? Was it April Fool's Day? "Sir, we need to send you to our CIO for secondary inspection. Right this way," Bill motioned.

Carl's face flushed as he wondered what kind of trouble he was in, especially since "trouble" could quickly escalate to handcuffs and holding cells. He also wondered why a Chief Information Officer would be doing secondary security inspections. Bill led him to Paulie's office, which housed a portly man with a sweet 80's mustache. The nameplate on his desk identified him as the Calculator Inspection Officer.

"I'm gonna need to see yer adding machine there, buddy," Paulie said, holding his hand out. Bill placed the HP-41CX in his palm. He gave it a closer look and grunted, "I'll have to confiscate this from you. It's got internal memory in it, y'see, so you could potentially use it to sneak secrets out. You can have it back at the end of the day, but don't let me ever catch you bringing this here again!" Bill led a calculator-less Carl back to the main security office.

On the way, Bill explained how programmable calculators were strictly forbidden in the facility. Paulie was in charge of enforcing this policy and took his job very seriously. If Carl wanted to bring a calculator, it would have to be a very basic model. Once Paulie approved it, an "AC" (Approved Calculator) sticker would be placed on the back to allow its entry. Feeling discouraged without his HP-41CX, Carl resigned himself to inhaling chalk dust for the rest of his time at Schlockdeed. At least he had a media pass, so he could still freely take floppy disks in and out of the facility.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!

https://thedailywtf.com/articles/calculated-security


Метки:  

A Switch for Grenk

Среда, 27 Февраля 2019 г. 14:30 + в цитатник

Let’s say you’ve got a project object in your code. A project might be opened, or it might be closed. In either case, you want to register an event handler to change the status- closed projects can be opened, opened projects can be closed. Now imagine you’re Antonio’s co-worker, Grenk.

No, this time, it’s not a matter of streams. Today, it’s ternary abuse, of the “why is this even here” sort.

switch(project.getStatus())
{
    case CLOSED:
    {
        //snip: re-open the project
        break;
    }
    case OPEN:
    {
        //snip: close the project
        break;
    }
}
registerEvent(projectDB.getStatus().equals(StatusProjectEnum.CLOSED) ? TypeEventProjectEnum.ENABLED : TypeEventProjectEnum.DISABLED, project.getId(), sessionUser,
                           project.getStatus().equals(StatusProjectEnum.CLOSED) ? "Enabled project " + project.getDescription() : "Disabled project " + project.getDescription());

getDao().update(project);

Let’s trace the logic. We start with a switch on the project status. If it’s CLOSED we open it, if it’s OPEN we close it. Then, we call the registerEvent method, and use a ternary on the project status to decide what parameters to pass to the method. The result is an unreadable mess, and it’s extra confusing because we just passed by a perfectly good switch. Why not just put a call to registerEvent in each branch of the switch?

Which, by the way, is exactly what Antionio did. During the code review, Grenk objected that Antonio’s version wasn’t as “DRY” as his, but the rest of the team agreed that this was more readable.

[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

https://thedailywtf.com/articles/a-switch-for-grenk


Метки:  

Beyond Brillant

Вторник, 26 Февраля 2019 г. 14:30 + в цитатник

We've all had cow-orker's who couldn't do their jobs. Some people have even had the privilege of working with Paula.

Jarad should be so lucky.

He worked at Initech in a small development group, building a Windows client tool that customers used to interface with their server. One day, they decided to port the app from .NET to Java. The powers-that-be recommended a highly regarded Lead Java Developer, Kiesha, from Intelligenuity, to lead the project. "Don't worry," they said, "Intelligenuity only employs the most brillant programmers."

At the first group stand up meeting of the project, their manager announced that they would use Eclipse for the Java project. Kiesha posited "I don't have Eclipse. Could someone please send it to me?" So Jarad sent her the link. At the next stand up, he followed up to ask if she had gotten Eclipse installed. She said "I was blocked because she had been unable to download it, so I waited for the next meeting to ask for help." Their manager jumped on her machine and solved her problem by clicking on the download link for her.

Fast forward to the next meeting and she said that she was still unable to proceed because "Eclipse was having some problem with 'JDK' and could someone please send me that?" Jarad sent her that link too. Several days later at the next meeting, she said "Eclipse isn't working because it needs a 'jar' file, so could someone please send one to me?" And after that, "Could someone please send me sample code for doing classes because Eclipse kept saying  NullPointerException".

Finally the manager changed the meeting structure. They would continue their usual standups for the Windows client, but they would add a separate dedicated meeting with just Kiesha. Eventually, they found out that she and her husband were buddies with a highly placed C** executive and his wife. The separate meeting was to "guarantee that she's successful," which meant their manager was writing the code for her.

One day, Kiesha told the manager that a customer was having a critical problem with the web portal, and that it was of the utmost importance that they have a meeting with the customer as soon as possible to help resolve the issue.

Their manager set up a meeting with the customer, himself, Kiesha, Jarad, and the project manager to solve it once and for all. The day of the meeting, the customer was surprised at how many support people and managers showed up. The customer explained. "The, um… 'portal problem' is that we asked Kiesha for the URL of the web portal? This could have been an email."

Sometimes, there is justice in this world, as Kiesha finally lost her job.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!

https://thedailywtf.com/articles/beyond-brillant


Метки:  

CodeSOD: The Serial Killer

Понедельник, 25 Февраля 2019 г. 14:30 + в цитатник

Debugging code on embedded devices introduces additional challenges to tracking down what's going wrong, especially as in many cases, you can't even rely on any sort of println debugging. I've worked with a few devices which my only debugging output is 3 RGB LEDs.

Serial devices, then, can be a godsend. For short runs, you can often just wire pin-to-pin, but for longer connections, you need some sort of serial transceiver chip. In most practical situations, the flow between two devices is CPU->UART->transceiver->cable->transceiver->UART->CPU. Apologies to the OSI model, yes, it's more complicated than this, but for our purposes, it's a useful illustration.

Stephen was debugging a board where the chip supported four UARTs, but the board had two different transceivers on it, each responsible for two different UARTs. What was supposed to happen was that when data arrived via the serial bus, an interrupt would fire and react to the message. None of that was happening.

It wasn't hard to find the method responsible for setting up the interrupts:


    void sysSerialHwInit2 (void)
    {
    int i;

    /* connect serial interrupts */

     for (i=0;icode>

The whitespace is as originally found, and it did an exceptional job of hiding the bug. If you just glance at this code, trying to understand its flow from its formatting, it seems pretty sane: set up the interrupts for our UART channels, and then set up the interrupts for our "chiptwo" channels.

Of course, that's not what's actually happening. "Whitespace matters," writes Stephen, and after he let his editor fix the whitespace, the actual flow of the code became clear:


    void sysSerialHwInit2 (void)
    {
        int i;
    
        /* connect serial interrupts */
    
        for (i = 0; i < N_UART_CHANNELS; i++)
            if (i8250Chan[i].int_vec)
            {
                (void) intConnect (INUM_TO_IVEC (i8250Chan[i].int_vec),
                                    (VOIDFUNCPTR)i8250Int, (int)&i8250Chan[i] );
                sysIntEnablePIC (i8250_devParas[i].intLevel);
                for (i = 0; i < N_XR17D_CHANNELS; i++)
                {
                    (void) pciIntConnect(INUM_TO_IVEC (INT_NUM_GET (xr17dChan[i].level)),
                         (VOIDFUNCPTR)xr17dInt, (int)& xr17dChan[i]);
                    sysIntEnablePIC (xr17dChan[i].level);
                }
            }
    }
    

A few missing curly braces meant that what was supposed to be two separate for loops were mashed into one for loop which didn't work.

It wasn't hard to fix the curly braces and the whitespace. It was harder to talk the other developers on the team into setting up their editors to use a consistent approach to whitespace.

[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

https://thedailywtf.com/articles/the-serial-killer


Метки:  

Error'd: No Scandinavian Pets Allowed

Пятница, 22 Февраля 2019 г. 14:30 + в цитатник

"I guess this is the price I pay for giving my Golden Retriever a unique (and secure) name," writes Robert N.

 

"C'mon Microsoft, everyone knows that NaN isn't allowed to have an ordinal," wrote Douglas M.

 

Geoff O. wrote, "This list of values is practically PLEADING to be translated."

 

"If Robert Reich said all that 4 decades, 9 years ago, he must have been REALLY ahead of his time!" Arezio B. writes.

 

Will N. wrote, "I know show runtimes shorten a lot when you cut out commercials, but this new show on iPlayer looks like it's going on FOREVER."

 

Eric B. wrote, "I’m moving to Taiwan. Apparently they have more days in a month than we do, and they’re Sundays!"

 

[Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!

https://thedailywtf.com/articles/no-scandinavian-pets-allowed


Метки:  

CodeSOD: Conditionally Exceptional

Четверг, 21 Февраля 2019 г. 14:30 + в цитатник

The beauty of structured exception handling is that it removes explicit conditional logic from your code. The conditions are still there, of course: a catch statement is essentially saying "if the exception type is X, then do this". But the strict syntax gives the compiler some freedom, and if you're using a language like Java, which favors checked exceptions (where methods declare what kinds of exceptions they might throw), there are all sorts of shortcuts the compiler might take to keep that efficient.

But hey, that's all implicit, and if there's one thing we've learned, "explicit is better than implicit". How can we make exception handling explicit? Well, our Anonymous submitter inherited some Java code which does just that.

Object obj = null;
try {
    obj = methodThatCanThrowVariousExceptions();
} catch (Exception e) {
    if (e instanceof ExceptionOne ) {
        //Code removed for anonymity
    }  else if (e instanceof ExceptionTwo ) {
        //Code removed for anonymity
    } else if (e instanceof ExceptionThree ) {
        //Code removed for anonymity
        }
    } else {
        //Code removed for anonymity
    }
}
return obj;

While this is pretty heavily anonymized, the highlights are pretty clear. Our methodThatCanThrowVariousExceptions passes its return to an Object. No specific kind of object, of course, just, y'know, a thing. A whatever. If we get a whatever, we return it, whatever it may be. Otherwise, we check each possible kind of exception… in an if. Because why use the basic syntax of a try/catch when you have an if instead?

While this code favors an explicit approach versus an implicit one, I'll leave the explicit language to describe it as implicit in this case.

[Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!

https://thedailywtf.com/articles/conditionally-exceptional


Метки:  

What's The Floating Point?

Среда, 20 Февраля 2019 г. 14:30 + в цитатник

Photograph of the San Francisco Mint Coin Adjusting Room. Tables have assay scales at each station. Coin counting... - NARA - 296577

There are a number of gotchas that trip up new programmers: the difference between declaring a variable and initializing it, the need for semicolons to terminate lines at times, and off-by-one errors, to name a few. All of us in the industry have met genius self-taught programmers who can put together extensive, well-architected applications in their sleep—but all of us have also met self-taught juniors who barely grasp the basics and think that's all they'll ever need. There's a reason degrees and formal training exist, after all.

Today's story happened when Olaf was fresh out of university, working his first non-intern job as a "trainee programmer." The company aimed to improve government health care management: a noble goal, for those who have never had the dubious pleasure of interfacing with healthcare systems. However, it was founded by a doctor with just a smattering of PHP knowledge, all self-taught in his minimal spare time.

Olaf came in with an eye to improving what was there using his knowledge of design patterns. PHP is a simple language to learn, but a hard one to master; much of the PHP software out there uses god objects and mingles code with layout, two big no-nos that are nevertheless taught in most online tutorials. Olaf began separating function from form, creating objects that could be reused to minimize the copy-pasting, and the like, happily bringing order to the chaos he'd been given.

Which is how he found himself in the boss's office, on the wrong end of a dressing-down.

"The other programmers won't understand this!" the boss cried. "It's too complicated. Why are you changing it? It works, just leave it alone!"

Disheartened, Olaf went back to work, checking out a clean copy of the master branch without his changes. Trying to ignore the bad practices, he began working on a bug in the accounting system, a bug marked "high priority" and "urgent" since it dealt with billing. Users would upload CSV files with information about what was spent, and the system would sum the values by category and create billing reports. However, there was a rounding error somewhere in the internals, leading to incorrect sums in a few important edge cases.

Olaf had more training than his coworkers, but no training is exhaustive. He was able to quickly determine that this was a floating point mathematical error. Because decimals aren't represented exactly in binary, the math will be wrong in a few edge cases. He went looking for the right way to handle decimal values in PHP. However, unlike Node or C#, it's actually fairly difficult to include external libraries in PHP, as the language has no built-in support for package management. He was unable to figure out how to add a library that would do the math correctly. Since the software was only doing sums, he advocated for integer mathematics: read in the value, remove the decimal point (so that $10.50 would be represented as 1050), do the math, then add the decimal point back when displaying.

One of the other junior devs loved the idea. The senior developer considered it—but the boss flat-out refused the suggestion. His take? "This isn't a floating-point error. This is because PHP is weakly typed, and it's trying to do summation as strings rather than numbers."

(For those who are curious: PHP does not use the "+" operator to concatinate strings. It uses "." instead. "hello " . "world" results in "hello world".)

The final solution the senior ended up implementing: separate the whole part from the fraction, so that our $10.50 charge becomes $10.00 and $0.50, then sum each portion separately.

Olaf didn't wait around to see what would happen when they discovered that the bug still existed, since they were still treating the cents portion as a floating point number. He found a better job in a better language and never looked back.

[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

https://thedailywtf.com/articles/what-s-the-floating-point


Метки:  

CodeSOD: Posting the Check

Вторник, 19 Февраля 2019 г. 14:30 + в цитатник

Coming from the US, I have a pretty simplistic model of how postcodes work. They’re either 5 or 9 digits, depending on how precise you’re being. I can validate that with a simple regular expression. There’s a lot of detail encoded in that number, including the central sorting facility and city or town I’m in, but I don’t usually care about those details. In any country with some sort of postcode system, while the pattern of the postcode may change, the complexity of it generally caps out pretty quickly. That’s sort of the point.

Maybe Sam’s co-worker didn’t know what regexes were. Maybe they’d read an article talking about how regexes were expensive, and were worried about performance. Maybe they wrote this method as part of a college assignment and added it to their personal snippet library and never thought about it again. Maybe they just hated their co-workers and were planting landmines for them to stumble across. Regardless, this is how they verified a postcode within their locale.

public bool checkPostCode(string Postcode)
{
    if (Postcode.Length < 9 && Postcode.Length > 5)
    {
        char[] array = Postcode.ToCharArray();
        int l = array.Length;
        bool end = false, start = false;
 
        if ((int)Convert.ToChar(array[l - 1]) <= 90 && (int)Convert.ToChar(array[l - 1]) >= 65)
            if ((int)Convert.ToChar(array[l - 2]) <= 90 && (int)Convert.ToChar(array[l - 2]) >= 65)
                if ((int)Convert.ToChar(array[l - 3]) <= 57 && (int)Convert.ToChar(array[l - 3]) >= 48)
                    if ((int)Convert.ToChar(array[l - 4]) == 32)
                        end = true;//return true;
 
        if (l == 6)
            if ((int)Convert.ToChar(array[0]) <= 90 && (int)Convert.ToChar(array[0]) >= 65)
                if (array[1] <= 57 && array[1] >= 48)
                    start = true;
 
        if (l == 7)
        {
            if ((int)Convert.ToChar(array[0]) <= 90 && (int)Convert.ToChar(array[0]) >= 65)
            {
                if ((int)Convert.ToChar(array[1]) <= 57 && (int)Convert.ToChar(array[1]) >= 48)
                    if (((int)Convert.ToChar(array[2]) <= 90 && (int)Convert.ToChar(array[2]) >= 65) || ((int)Convert.ToChar(array[2]) <= 57 && (int)Convert.ToChar(array[2]) >= 48))
                        start = true;
 
                if ((int)Convert.ToChar(array[1]) <= 90 && (int)Convert.ToChar(array[1]) >= 65)
                    if ((int)Convert.ToChar(array[2]) <= 57 && (int)Convert.ToChar(array[2]) >= 48)
                        start = true;
            }
        }
 
        if (l == 8)
        {
            if ((int)Convert.ToChar(array[0]) <= 90 && (int)Convert.ToChar(array[0]) >= 65)
                if ((int)Convert.ToChar(array[1]) <= 90 && (int)Convert.ToChar(array[1]) >= 65)
                    if ((int)Convert.ToChar(array[2]) <= 57 && (int)Convert.ToChar(array[2]) >= 48)
                        if (((int)Convert.ToChar(array[3]) <= 90 && (int)Convert.ToChar(array[3]) >= 65) || ((int)Convert.ToChar(array[3]) <= 57 && (int)Convert.ToChar(array[3]) >= 48))
                            start = true;
        }
 
        return start && end;
    }
    else
    {
        return false;
    }
}

Well, that’s a thing. I really like how the first check cycles backwards through the string. I have no idea what locale is being targeted by this code, and I’m not about to trace through it to find out. Instead, I’ll just draw your attention to the //return true commented out, which gives us a sense of the mindset of the developer responsible for this. The whole thing says, “hope you have the ASCII table memorized, sucker”.

[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

https://thedailywtf.com/articles/posting-the-check


Метки:  

The Three-Month Itch

Понедельник, 18 Февраля 2019 г. 14:30 + в цитатник

Compass in coil

It was March 2016, and Ian was in need of a job. Fairly early into his search, he was lucky to find a tiny startup in need of someone with Python architecture and design skills. By "tiny," we mean that there were only three other developers working for Jack, the founder.

Ian interviewed with Jack directly. After a technical test, he learned more about the company's pet project: a nearly-finished prototype of an iOS app. Once a user synced their phone with a wrist-worn heart rate monitor, the phone would play appropriate music for whatever the user was doing. It was primarily intended to help users reach a target heart rate while exercising. The app also used the phone's accelerometers to track the user's pace as they moved around, data that Jack claimed would be valuable for research into Parkinson's disease. He even had scientific papers from top universities to back up the claim. The prototype application, in its current state, wouldn't scale. Thus, Jack needed Ian to design a new backend system to store data and handle requests.

Jack was friendly and personable, and his enthusiasm was contagious. Ian accepted on the spot, and started the next day. His office was cramped, but it was his. He got to work designing the requested backend.

Two weeks passed. Then, early on a groggy Monday morning, Jack breathlessly pulled his dev team into a meeting room. The bright light beaming from his Powerpoint presentation drilled into everyone's retinas.

"I've been doing a lot of thinking," Jack prefaced. "We're a brand new startup. Nobody knows about us, right? We gotta do something to build up name recognition. So, here: we're gonna scrap the music part of the app, and focus solely on data collection."

Ian stifled his instinctual What?! Not only were two weeks of work down the drain, but the data collection part of the app was an entirely optional feature at present.

Jack flipped to a slide that showed the metrics he was now interested in tracking for each user. There were so many that the tiniest of fonts had been used to fit them all in. Ian squinted to read them.

"If you build a big enough haystack, a needle will appear!" Jack said. "We'll make the app free so it's a totally opt-in experience. The data we collect is the real prize."

Investment capital was spent on posh downtown office space; for free app developers, only the very best would do. Jack also hired a second iOS developer, a data scientist, and an intern.

"But don't give the intern anything important to do," Jack told the full-timers.

Once Ian settled into his new digs, he began architecting a new system that would somehow capture all the required data.

Three months later, Jack threw it out. "No apps! We need a new direction!"

Jack's new vision was a website where people would sit down and input what songs they listened to when sleeping, exercising, and performing other activities.

"People love to talk about themselves," Jack said. "They don't need to be paid to give us their data!"

A frontend dev was hired to build the website. Soon after it went live, Jack bragged to investors that the website had hit 1 million unique visitors. In reality, the site had handled around 300 submissions, half of which had come from a single person.

Three months later, guess what happened? Jack scrapped the faltering website in favor of a Slack bot that would respond to "Play ${song} by ${artist}" by looking it up on Spotify and providing a link. The Spotify widget would play a 30-second preview, or—if the user were logged in with a Spotify Premium account—play the whole song.

"That's it? How's that going to make any money?" By this point, the developers were no longer holding back their objections.

"We'll charge a subscription fee," Jack answered, undaunted.

"For a chat bot?" Ian challenged. "You already need Spotify Premium for this thing to fully work. If we want people to pay more money on top of that, we have to provide more features!"

"That's something we can figure out later," Jack said.

Jack had the intern develop the company's new flagship product, going against the wishes of Jack from six months earlier. The intern gave it his best shot, but soon had to return to school; the unfinished code was unceremoniously tossed into the frontend developer's lap. With help from one of the iOS developers, he finished it off. And what was Ian up to? Setting up monitoring dashboards and logging at Jack's insistence that they'd attract enough users to justify it.

Three more months passed. A number of "features" were added, such as the bot nagging users in the Slack channel to use it. As this behavior violated the Slack TOS, they were prevented from putting their app in the app store; Jack had to hand out links to a manual install to interested parties. The product was first given to 50 "super-friendly" companies Jack knew personally, of which only a handful installed it and even fewer kept using it after the first day. Jack then extended his offering to 300 "friendly" companies, with similar results.

Ian's breaking point came when Jack insisted he pull overtime, even though there was no way he could help the other developers with their tasks. Nevertheless, Jack insisted Ian stay late with them to "show solidarity." Finally at his wit's end, Ian put in his two weeks. His final day coincided with the general release of the Slack bot, during which he watched a lot of very flat lines on dashboards. When he left the posh office for the last time, the startup still had yet to earn its first cent.

Fortunately, Jack had a plan. After Ian left, he scrapped everything to start on fresh on a new product. No, it wouldn't make any money, but they needed name recognition first.

[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

https://thedailywtf.com/articles/the-three-month-itch


Метки:  

Error'd: Nobody is Perfect

Пятница, 15 Февраля 2019 г. 14:30 + в цитатник

"Google notified me that it needs help from a human and then displayed me this image," Jeff K. wrote, "I think I may need some help too."

 

"I'm really glad that Pizza Hut's batch job finished up...does this mean I get one of those 16,867,183 coupons?" Lincoln K. wrote.

 

Stefan Z. writes, "Testing is important for any business' site. Even if, sometimes, it's in production."

 

"I give you The Sam's Club business model:

  1. Drop password length limit from 25 to 12
  2. Apply new validation to existing passwords
  3. ???
  4. Profit!" George writes.

 

"My feedback for World of Tanks is as follows - 'I had a VERY negative experience'," writes Piotr.

 

James P. writes, "So...which one do I install first?"

 

[Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!

https://thedailywtf.com/articles/nobody-is-perfect


Метки:  

CodeSOD: Getting to YES

Четверг, 14 Февраля 2019 г. 14:30 + в цитатник

“We’re a dynamic, multi-paradigm organization, and we do most of our new development in a blend of Ruby and Go. We’re not the kind of company that is dogmatic about tools though, we just want to deliver the best product for our customers.”

That’s what Delphia was told in the interview. She didn’t quite grasp why they were mixing those two techs in the first place, but the interview went well, and she took the job. It was then that she discovered that everything she’d been told was technically true.

The company had just finished a sprint where they tried to pivot and reimplement their 15 year old codebase in Rails and Go. At the same time. It was difficult to tell from the code if this were a case where they did both together, or they were parallel projects, or frankly, if there was any coordination between either of them. That was their new development.

The company didn’t do much new development, though. The core of the company’s business was a 7,500 line PHP file which contained a single form. It depends on includes from dozens of other files, some of which depend on functions defined in the main PHP file, and thus can’t be used in any other context but that include. It’s less spaghetti code or even a big ball of mud, and more a career killing meteorite.

But it makes more money for the company in a day than Delphia can rightly count.

One function that Delphia kept seeing invoked a bunch was yesorno. It was used almost everywhere, but she had never seen the definition. So, curious, she went digging. And digging. And digging. Someplace around the fifteenth or thirtieth include file she read through, she found it.

function yesorno($in) {
  if($in == 'YES') return 'YES';
  else             return 'NO';
}

That indentation, by the way, is typical of about 30% of the codebase, maybe less. You wouldn’t expect any sort of consistency in this kind of code, would you?

[Advertisement] ProGet supports your applications, Docker containers, and third-party packages, allowing you to enforce quality standards across all components. Download and see how!

https://thedailywtf.com/articles/getting-to-yes


Метки:  

A Backup Pipeline

Среда, 13 Февраля 2019 г. 14:30 + в цитатник

“Um… can you come take a look at something for me?”

Pat looked up from happily hacking away at some new features to see Milton hovering at the edge of the cubicle.

“I think I messed up,” Milton added.

One of their company’s main internal systems was a data processing pipeline. “Pipeline” might be a bit generous, as in practice, it was actually a webwork of shell scripts and Python that pulled data in from files, did “stuff” to that data, and dropped the results into other files, which could then be read in by different scripts. In actual use, this usually meant people grabbed the latest version of the scripts from source control, modified and tweaked how they executed to answer one specific data-related question, and if that particular process seemed like it might have value, they’d clean the code up a bit and then try and merge it back up into source control. Otherwise, if they didn’t think they’d need it again, they’d just reset back to HEAD.

Some folks, though, like Milton, mostly kept their own copy of all the scripts. Or in Milton’s case, multiple copies. Milton knew the data processing pipeline better than anyone, but the vast majority of that knowledge was locked up in his personal scripting library.

“I was thinking I should probably try and contribute changes back upstream,” Milton said. “So, like, I’ve got a script that’s called by a script, which is called by a script, and it depends on having a bunch of shell variables created, like $SETUP_DIR.”

Pat nodded along.

“So I wanted to refactor that into an argument, so other people could use it. And I did… but I forgot to change the calling scripts to pass the argument before I tried to test it.”

Specifically, Milton’s script had a line like this:

#!/bin/sh

rm -rf $SETUP_DIR/*/

Which he refactored into a line like this:

#!/bin/sh

rm -rf $1/*/

Shell scripts don’t care if these variables exist or not. Milton had an environment which always guaranteed $SETUP_DIR existed. But $1 is the first argument, and if you don’t pass an argument, it’s nothing. So Milton’s new script, when executed with no arguments, expanded to rm -rf /*/- deleting everything his account had access to.

Mostly that meant lots of failed attempts to delete files he didn’t have the rights to. It also meant his home directory went away, along with his entire packrat pile of spaghettified scripts that were absolutely impossible to reconstruct, as they’d never been placed in source control.

“There’s a way to fix this, right?” Milton asked.

“I mean, sure. You can restore from the last backup you took,” Pat said.

While all the Windows boxes were running an automated backup tool, installed automatically, none of the Linux boxes were so configured. The support team took the stance that if you were technical enough to be running Linux and writing shell scripts, you were technical enough to set up your own backup solution. There was a SAN available to everyone for exactly that purpose.

“Oh, I… never set up a backup,” Milton whispered. “Well… at least I didn’t push?”

Pat wondered if Milton was learning the right lesson from this mistake.

[Advertisement] Ensure your software is built only once and then deployed consistently across environments, by packaging your applications and components. Learn how today!

https://thedailywtf.com/articles/a-backup-pipeline


Метки:  

CodeSOD: A Knotted String

Вторник, 12 Февраля 2019 г. 14:30 + в цитатник

Rita caught a weird bug. It was weird, in part, because there hadn’t been any code changes in their label printing application for ages. Yet, there was a sudden new bug. Labels were printing with what was obviously unicode garbage. Interestingly, the application definitely supported unicode- there had been a huge effort a few years back to move the C++ code from chars to wchars.

Rita started debugging, and confirmed that when the label text was populated, memory stored correct values. By the time the data was printed, it no longer did. Obviously, there was something wrong with memory management- something was touching the end of the string and throwing off the output. That was an easy enough bug to make in C++, but tracing through 7,000 lines of label printing code to figure out where things got thrown off was more of a chore, especially with the… “friendly” variable naming convention the original developer had used.


  wchar_t* xyz = new wchar_t(wcslen(abc));

That doesn’t look like much, does it? xyz is a pointer to a wchar_t, a pretty typical way to represent a string, and then we initialize it to point to a new wchar_t with a size equivalent to the length of an input string, right?

Of course not. There’s an important difference between new wchar_t(10) and new wchar_t[10]. The latter makes a block of memory capable of holding ten wide characters. The former makes a single wide character and initializes it with the value 10. So xyz points to a single character, but this is C++. If you disable enough warnings, there’s nothing that will stop you from abusing that pointer and running off the end of memory.

The real WTF though, is that this wasn’t a bug introduced back when they switched to wchar. Going back through the source control history, Rita found the previous version:


char* xyz = new char(strlen(abc));

It had the same bug. The bug had gone undetected for all this time because the message string had been short enough that nothing else was touching that section of memory. It was only after a user had recently tried to add a slightly longer message that the buffer overrun started causing problems.

[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

https://thedailywtf.com/articles/a-knotted-string


Метки:  

CodeSOD: The Double Bind Printer

Понедельник, 11 Февраля 2019 г. 14:30 + в цитатник

Printer jams are an unavoidable circumstance. Paper might not seem sticky, but static electricity and humidity can to horrible things, and all the protections in the world can't stop them. Printers are also objectively terrible, and always have been.

Years ago, when Coyne T was a fresh-faced youth, he supported an aging COBOL-based warehouse system. Their reports went to a noisy continuous feed line printer. The printer was a finicky beast, and no matter what sacrifices were made before printing, it had a tendency to devour pages, or have the gears slip and misprint lines. Because the report data came straight from a COBOL job, there was no cached output to reprint- the entire reporting process would need to be re-run every time the printer got angry.

About thirty pages of a report got chewed up a few days after Coyne joined the team. As the new kid, re-running the report fell to him. "But, before you go and re-run the report," the team lead, Herschel, said, "there's a few things you should know."

Herschel laid out the key facts. The report generating program didn't just generate the report. It also could clear the monthly totals and update the day's inventory as part of running the report. Doing either of those in the middle of the day was absolutely wrong, and would create a lot of manual work to fix it. Even worse, doing both of those during the same run would stomp all over the data files and absolutely corrupt the entire mainframe.

"Fortunately, I added two flags- CLEAR-SWITCH and UPDATE-SWITCH. Just make sure they're both set to 'N', and you should be fine."

Coyne checked and double checked the instructions, ensured that the flags were definitely set to 'N', and then ran the report.

After the mainframe team had restored from backup and recovered as much of the data that they could (losing only the past three days worth of inventory), Coyne was called out on the carpet to explain how he'd destroyed the database. Despite being a newbie, Coyne had been cautious from the start, and reviewed the instructions which Herschel had given him, as well as how he'd verified that he'd followed the instructions. But Coyne had also gone the extra step, to look up the code block which checked those flags. He came to the meeting prepared.

IF NOT CLEAR-SWITCH = 'Y' SET RUN-UPDATE TO TRUE END-IF IF NOT UPDATE-SWITCH = 'Y' SET RUN-CLEAR TO TRUE END-IF

Now, first off, one might hope that if two flags should never be used at the same time lest they destroy all the data, there might be some logic to make them mutually exclusive. There is no such logic, but if you look closely, you can see some illogic that I suspect was meant to accomplish that goal.

If the CLEAR-SWITCH variable is not 'Y', then the code sets… RUN-UPDATE. And RUN-CLEAR is controlled by UPDATE-SWITCH. The result is an odd block of code: if either one of the switches is disabled, by being set to anything that isn't 'Y', this code works. If both of the switches are enabled, by being set to 'Y', then this code won't run either step. In the case where both switches are explicitly disabled, then both steps will be run (and the data will be destroyed).

Herschel warned Coyne that "only an idiot would run a job without reading the code first, you should have been more careful," but since Coyne was only a junior, and had followed the instructions, nothing more came from that meeting.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!

https://thedailywtf.com/articles/the-double-bind-printer


Метки:  

Error'd: Quite Powerful Errors Indeed

Пятница, 08 Февраля 2019 г. 14:30 + в цитатник

"I was considering this recorder for my son, but I think 120W might be a bit over the top," writes Peter B.

 

"Yep, looks like the test works to me," writes Stefan S.

 

Lincoln K. wrote, "Hertz may have Ultimate Choice(tm) but apparently not Ultimate QA."

 

"Consider a situation where seven electric vehicle chargers were installed and they were working ok, but monitoring wasn't working so great. After two weeks of finger pointing and 'not my fault' emails, an agreement was reached - inspect the terminal sockets and replace any networking cables. In the end, what happened was that an Electrician been 'promoted' to 'network technican' for a day. The guy's boss must have said It's just a tiny cable...a little smaller than your used to, just do as usual. Poor guy he stripped 112 wires (7 cables * 2 ends * 8 wires) by hand," Jon B. wrote.

 

Adam G. writes, "Something tells me I will not be contacted shortly."

 

Robert wrote, "Usually I'm very careful who I'm sharing passwords with, but in this case, I think I can make an exception."

 

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!

https://thedailywtf.com/articles/quite-powerful-errors-indeed


Метки:  

CodeSOD: A Policy Exception

Четверг, 07 Февраля 2019 г. 14:30 + в цитатник

“So, we have a problem. A… a big one.”

Andrea C worked for an insurance company. In terms of software development, a “problem” meant she’d misfiled one of her TPS coversheets or something like that. A big problem meant she’d accidentally checked in code that contained a comment with some profanity in it.

“It’s actually, well, it’s actually huge,” her boss continued.

She’d never had a “huge” problem before.

Someone had discovered that, if they knew a customer’s policy number and were currently logged in- they could see that customer’s policy. It didn’t have to be their policy. Any policy, so long as they had a valid login and the policy number.

That was pretty huge. Andrea hadn’t gotten too deep into that section of the application before, but the original developer had moved on, so it was time for her to dig in. She pulled up the JSP code which served the page.


"> --%>
	

N.

// SNIP: displays policy details

Let’s start with names. isValidPolicyNumber isn’t just a validator- it uses the fiscalCode to determine if this customer is allowed to see that policy number. It also checks that the policy number exists, that it’s a valid and active policy. And all that information is encoded into a single boolean value.

And of course, of course if that boolean value is false, we throw an exception. Flow of control by exceptions is always a great choice, especially when the only thing you do with the exception is set a flag.

The sane thing, at this point, is to bail. We can’t display this policy. But the code doesn’t bail, it actually goes right back to the database to fetch the policy. A policy that it may have already decided is not valid in this context.

When Andrea found this much, she thought she’d figured out the actual bug, but reading on revealed the next step. The test only surrounds the display of the header.

No one had touched this code in years. Pretty much since their new website launched in 2009, this code had been sitting in production.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!

https://thedailywtf.com/articles/a-policy-exception


Метки:  

CodeSOD: Double Up

Среда, 06 Февраля 2019 г. 14:30 + в цитатник

Carl works in research, and like most research organizations, half their code is carelessly glued together GUI tools, command line interfaces, and shell scripts. The other half, the half which does the real work, is Fortran. Sure, the code was written forty years ago, but the laws of physics haven’t changed, so it’s still good and it’s still fast.

Carl usually doesn’t have to touch the Fortran half. Instead, he usually looks at the other bit. Most things are run from shell scripts, and most of the work of the shell scripts is getting environment variables configured so that they Fotran code can actually run its model without having a heart attack.

So, for example, one of those environment variables is WORKINGDIR. WORKINGDIR holds a /very/long/path/to/a/deeply/nested/folder/someplace The Fortran model code also needs to know the location of the SYSDIR, which is always exactly two levels up from WORKINGDIR. No, the Fortran code can’t figure this out on its own, it’s too busy doing calculus. The shell script needs to figure it out.

The shell script which calculates it throws in a little wrinkle though: # calculate dir 2 levels up (Program doesn't allow .. in pathnames). So, no $WORKINGDIR/../.. here.

There are a number of ways one could solve this problem. The wrong way to solve this problem is this ksh script…

# calculate dir 2 levels up (Program doesn't allow .. in pathnames)
tmp=`echo $WORKINGDIR | tr -d /`
wctmp=`echo $tmp | wc -m`
wcwrk=`echo $WORKINGDIR | wc -m`
(( up2 = $wcwrk - $wctmp - 1 ))
export SYSDIR=`echo $WORKINGDIR | cut -d / -f 1-$up2 `

This code starts by using tr to strip out all the “/” characters. Then it counts how many characters are in the trimmed down version, and how many are in the original. The difference between these is the total number of directories in the path. Subtract another one from that. Then we use the cut command to grab from the 1st “/” character in the original path, up to the penultimate “/” character. Good news: this code is pretty confident $WORKINGDIR never ends in a slash, so this guarantees that we go up two levels.

Carl replaced this with the following one-liner: export SYSDIR=${WORKINGDIR%/*/*}, which accomplishes the exact same thing.

[Advertisement] ProGet supports your applications, Docker containers, and third-party packages, allowing you to enforce quality standards across all components. Download and see how!

https://thedailywtf.com/articles/double-up


Метки:  

Поиск сообщений в rss_thedaily_wtf
Страницы: 124 ... 75 74 [73] 72 71 ..
.. 1 Календарь