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

Поиск сообщений в 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 ленты.
По всем вопросам о работе данного сервиса обращаться со страницы контактной информации.

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

Representative Line: It Only Crashes When It Works

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

We already know that Kara’s office has a problem with strings. Kara’s back again, with more string related troubles.

These troubles are a bit worse, once we add in some history. You see, some of their software does machine control. That is to say, it sends commands to some bit of machinery, which then moves or extrudes or does whatever the machine does. Kara wasn’t specific, only granted that this machine was neither large enough or mean enough to kill someone. Minor cuts, burns, scrapes, bruises and damage to the equipment itself is still possible, but nobody will die.

Once upon a time, the bulk of this code was written in C. Then someone wanted a better UI. So that C code got replaced by the perfectly natural solution of… Visual Basic. There’s still some C in there somewhere, hidden behind interops and marshalled calls to native code, but most of the GUI and logic is pure VB.Net. Which brings us to our representative line.

Dim errorMsg As String = somePieceOfHardware.PerformSomeOperation(index).Replace("\r\n", vbCrLf)

As you might gather, someplace deep under the PerformSomeOperation method, commands are sent to the machine, and any errors come back in the form of a string. This string may contain a “\r\n”, which is the typical Windows line-terminator (carriage-return, line-feed), so we’ll Replace the carriage-return/line-feed with vbCrLf which is… a carriage-return/line-feed.

That’s not what ended up with Kara looking into this line, however. Kara was dragged in when the program started crashing, especially when their machine successfully executed PerformSomeOperation without error- because when there was no error, there was no string returned. So Replace was called on a null object, which obviously doesn’t work and raises a NullReferenceException.

Despite Kara’s assurance that this machine can’t kill you, this code can hurt you in far worse ways than mere death.

[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/it-only-crashes-when-it-works


Метки:  

CSS (Under)Performance

Вторник, 08 Января 2019 г. 14:30 + в цитатник

Heterobranchia composite 02

Ah, WordPress. If you hadn't heard of it by reputation, it sounds pretty good: one platform where you can build a blog, an e-commerce site, an app, or some combination of all of the above. Their site is slick, and their marketing copy sounds impressive: "Beautiful designs, powerful features, and the freedom to build anything you want. WordPress is both free and priceless at the same time." With WordPress, the hype insists, anyone can build a website without having to know anything about coding. Just pick a template, add free modules, and it'll look great without any effort.

If you've worked anywhere remotely connected to web design, you've heard of WordPress, and likely by reputation. The engine has maintained backwards compatibility since day one, which means it's the usual spaghetti system of duct tape and prayers you get when you prioritize backwards compatibility over systems engineering. It was more of a success than the designers intended, having been built solely as a (pretty decent) blogging platform at first, so the more use cases it expands to cover, the worse the learning curve becomes. Many web designers refuse to touch the system at all, preferring to roll something by hand that they understand than to untangle the snarl of "free" modules their clients installed when something goes wrong.

Two days before launch, Lukas was nearly done with a contract job: a custom marketing site with a contact form, exactly the kind of thing Wordpress has for Use Case #2. Testing the site before handing it over, he noticed one page loading slowly. VERY slowly. Like, 60 seconds slowly.

It seemed odd that a page with only static resources could even be that slow, so he ran a profile on the page:

For those of you who don't speak browser profile, that's the CSS engine that's stalling out for a whole minute. Usually, unless you're doing awful things in your CSS or have megabytes worth of it to render, the CSS engine is very fast; the usual culprit in Wordpress is client-side Javascript. But the CSS looked perfectly fine—messy and WordPressy, but fine, once it was all compiled.

Searching for answers, Lukas compared the markup on the page to the CSS stylesheet, trying to deduce what it was doing. A fancy heading here, a custom font there ... everything looked normal until he got to the top of the footer area, where he found the totally normal and not at all strange sequence of 131,074 empty paragraph tags.

Did I mention WordPress is built in PHP?

Some rogue bit of PHP code had gone into a horrible loop, dumping out empty paragraph tags 131,074 times right before the footer element. Pages upon pages of

with nary a

in sight. Paragraph tags default to display:block, meaning every time the engine gets to one, it causes the browser to execute layout, paint, and composite operations on the rest of the page—including the up to 131,073 other paragraph tags it may have already encountered. And this gnarly bit of nothing began after 1,482 lines of useful HTML, so it wasn't as if the page were tiny to begin with.

It gets better: this was all just before the custom footer, which can have inline CSS in WordPress, as it's a quick way to tweak a theme without having to create what's called a "child theme." The client had some inline CSS in place, and yes, it applied to the paragraph tag. It set padding-bottom: 0px !important;, forcing the CSS engine to re-render the entire set of paragraph tags once more.

And that's why no matter how good platforms become, no matter how rich the plugin ecosystem, there will always be work for web devs.

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

https://thedailywtf.com/articles/css-under-performance


Метки:  

CodeSOD: Without Compare

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

Operator overloading is a messy prospect. In theory, it means that you can naturally extend a language so that you can operate on objects naturally. An introductory CS class might have students implement a Ratio or Fraction class, then overload arithmetic operators so you can (a + b).reduce().

In practice, it means you use the bitshift operator also as the stream insertion operator. Thanks C++.

Java decided to chuck the baby out with the bathwater, and simply didn't allow operator overloading, but this introduced its own challenges. How do I tell if one instance of MyObject type is greater than another instance? That's important if I want to sort these objects, for example.

Thus, Java has the Comparator interface. Implement Comparator and now you can compare two instances of that object. The comparator object can be passed to all sorts of built-in methods for sorting, filtering, etc. At least, that's the theory.

An anonymous submitter found this unique approach to that problem.

private class CustomComparator implements Comparator<Communication> { @Override public int compare(Communication o1, Communication o2) { Integer p1 = 0; Integer p2 = 0; try { p1 = Integer.parseInt(o1.getPriority()); p2 = Integer.parseInt(o2.getPriority()); } catch (Exception e) { return 0; } if (p1 > p2) return 1; if (p1 == p2) return 0; if (p1 < p2) return -1; return 0; } }

Let's take it from the top. I understand that this is a private inner class, so while the name isn't going to be visible to any other code modules, CustomComparator is a terrible name. Especially because you know the developer responsible for this named all the private inner classes CustomComparator. Try searching for a specific one in your codebase.

The real WTF, though, is actually getPriority. The priority is a string. It might be a string which holds a number, but there's nothing in the application which enforces that. This of course means that the parseInt can fail, and that means that we return zero- we claim that these two Communication objects are equal to each other.

So, a Communication with a priority of "ASAP" is equal to a Communication with a priority of "0", "Foo", "12", "How does this even work?", and "13", but "12" and "13" aren't equal to each other. Welcome to non-transitive comparisons.

As you can imagine, this leads to idiosyncratic output. None of the end users really understand the sort order of their communications. It'd be simple to fix in a useful way, but, as our anonymous submitter adds:

I felt an urge to change this to something like p1.compareTo(p2) but this piece of code is inside a critical piece of the backbone of the application, so no unneeded modifications allowed.

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

https://thedailywtf.com/articles/without-compare


Метки:  

Error'd: All Aboard the System Bus

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

"The classic 'If transportation had evolved at the same pace as computers...' comparison is no longer merely academic as this TTC streetcar proudly displays it's nearing 32K RAM," Carlos writes.

 

"I guess if it's good enough for the people of ${city:capatilized}..." writes Philip J.

 

Greg wrote, "I'd consider amending to my birth certificate if it'd appease this form."

 

"Either this preview image is a mistake, or I have a serious misunderstanding of how sound mixing works," Steve B. writes.

 

"Even in a simple survey, Google finds date-math hard," wrote Eion Robb.

 

"After finding my DHL Express shipment hadn't been picked up at the scheduled time, their service desk told me that the shipment number could not be found and may be expired and to refer to their website," Thiadmer R. writes, "So, I went into the help section to see how long a label stays valid, and well, I don't think even knowing Latin would help."

 

[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/all-aboard-the-system-bus


Метки:  

CodeSOD: Is Num? I'm Numb

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

"The hurrider I go, the behinder I get," is one of the phrases I like to trot out any time a project schedule slips and a PHB or PM decides the solution is either crunch or throwing more bodies at the project.

Karl had one of those bosses, and ended up in the deep end of crunch. Of course, when that happens, mistakes happen, and everything gets further behind, or you're left with a mountain of technical debt because you forgot that Integer.TryParse was a function in C#.

Which is what happened to Karl. And that's why Karl wrote… this.

private static bool IsNum(string num) { for (int i = 0; i < num.Length; i++) { for (int j = 0; j <= 10; j++) { if (j == 10) return false; if (num.Substring(i, 1) == j.ToString()) break; } } return true; }

This is an impressive brain-fart. Nested loops, multiple escape clauses from the inner loop which return control to different places. All the calls to Substring and ToString.

Unfortunately for Karl, this code shipped, and unless there are any show stopping bugs, none of the existing code is ever to be touched again. Everyone should be focused on writing new features for the next release.

[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/is-num-i-m-numb


Метки:  

Representative Line: Innumerable Enum

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

Ah, the enumerated type. At its core, it's really just a compile-time check to ensure that this constant containing 1 isn't getting confused with this other constant, also containing 1.

We usually ignore the actual numbers in our enums, though not always. Perhaps, though, we should just pay more attention to them in general, that way we don't end up with code like Andrew found.

public enum AddressPointerTable { Default, Two }

This is C#, but the behavior would be more or less the same in any C-like language. The first entry in the enum has the value 0. The second has the value 1.

So Two == 1.

Now, the real problem with this code is that these are just terrible names, all the way around, and it's impossible to even guess what they might mean out of context. But the part that had Andrew and his co-workers laughing was that two is one.

[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/innumerable-enum


Метки:  

Best of…: 2018: Another Bitmask Fail

Вторник, 01 Января 2019 г. 14:30 + в цитатник
To wrap up our best-of year in review, here's yet another case where a simple problem is solved using simple tools, and everything still turns out entirely wrong. Original. And a happy New Year to you all! -- Remy

Sucre blanc cassonade complet rapadura

As we've seen previously, not all government jobs are splashy. Someone has to maintain, for example, the database that keeps track of every legal additive to food so that paranoid hippies can call them liars and insist they all cause cancer and autism. Today's submitter, Cass, had just released an update when users started getting the dreaded blue Internal Error screen—never a good start to the week.

Everything that's added to food is added for a reason; otherwise, why spend money doing it? The additive website allows searching by function, as well as by name. For example, some items might be alternative sweeteners, while others might be coloring agents. The problem of the week turned out to be in the stored procedure related to this particular search, which was intuitively titled prc_AdditiveRegulation_GetResults_NEW. Not to be confused with the entirely unused prc_AdditiveRegulation_GetResults, prc_AdditiveRegulation_GetResults_DEV, or prc_AdditiveRegulation_GetResults_PROD.

As Cass quickly discovered, prc_AdditiveRegulation_GetResults_NEW is a hefty chunk of code. 1044 lines, to be precise, all dedicated to returning a list of additives and their functions. After hours of searching, Cass managed to isolate the portion that was causing the problem:


UPDATE #techfunction
 SET bitNum = TableRank.PowerRank
 FROM (SELECT RowId,TechfunctionId,POWER(2.0,DENSE_RANK() OVER (PARTITION BY TechFunctionId ORDER BY RowId)) AS PowerRank    -- need to use 2.0 instead of 2 to avoid arithmetic overflow error (mark, 6/11/2012)
                         FROM #TechFunction t2) TableRank
 INNER JOIN #techfunction t
         ON t.rowId = TableRank.RowId
         AND t.techfunctionId = TableRank.TechFunctionId

In case it's been a while since you took CompSci 214: Insane Data Algorithms, allow me to translate: this code assigns each function an additive can perform to a specific power of 2. Later, these numbers are added together so that groups of technical functions effectively have a distinct number, allowing them to be used as a bitmask to search for the additives. "Clever" at its finest.

Years later, the number of functions surpassed 32, causing the POWER function to overflow a simple integer. Mark, who worked at least two generations of developers before Cass, must have fixed this by forcing it to use a larger data type by casting the 2 as float type which would then be converted back to a Bigint for storage. (This likely caused a small performance dip, as it can no longer bitshift when calculating powers, but it's still "clever," and that's what really matters.) With Cass' release, the number of additives exceeded 64, making it overflow the Bigint data type as well.

The best part? None of this was necessary. Cass traced every instance where the proc was called: the bitNum was never used, despite being always calculated. She removed it, and the errors cleared up overnight.

[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/2018-another-bitmask-fail


Метки:  

Best of…: 2018: The Wizard Algorithm

Понедельник, 31 Декабря 2018 г. 14:30 + в цитатник
NIH syndrome causes untold suffering in the world, but for just a few pennies a day, you can help. Or maybe not, but not-invented-here meets password requirements in this story from June. --Remy

Password requirements can be complicated. Some minimum and maximum number of characters, alpha and numeric characters, special characters, upper and lower case, change frequency, uniqueness over the last n passwords and different rules for different systems. It's enough to make you revert to a PostIt in your desk drawer to keep track of it all. Some companies have brillant employees who feel that they can do better, and so they create a way to figure out the password for any given computer - so you need to neither remember nor even know it.

Kendall Mfg. Co. (estab. 1827) (3092720143)

History does not show who created the wizard algorithm, or when, or what they were smoking at the time.

Barry W. has the misfortune of being a Windows administrator at a company that believes in coming up with their own unique way of doing things, because they can make it better than the way that everyone else is doing it. It's a small organization, in a sleepy part of a small country. And yet, the IT department prides itself on its highly secure practices.

Take the password of the local administrator account, for instance. It's the Windows equivalent of root, so you'd better use a long and complex password. The IT team won't use software to automate and keep track of passwords, so to make things extremely secure, there's a different password for every server.

Here's where the wizard algorithm comes in.

To determine the password, all you need is the server's hostname and its IP address.

For example, take the server PRD-APP2-SERV4 which has the IP address 178.8.1.44.

Convert the hostname to upper case and discard any hyphens, yielding PRDAPP2SERV4.

Take the middle two octets of the IP address. If either is a single digit, pad it out to double digits. So 178.8.1.44 becomes 178.80.10.44 which yields 8010. Now take the last character of the host name; if that's a digit, discard it and take the last letter, otherwise just take the last letter, which gives us V. Now take the second and third letters of the hostname and concatenate them to the 8010 and then stick that V on the end. This gives us 8010RDV. Now take the fourth and fifth letters, and add them to the end, which makes 8010RDVAP. And there's your password! Easy.

It had been that way for as long as anyone could remember, until the day someone decided to enable password complexity on the domain. From then on, you had to do all of the above, and then add @!#%&$?@! to the end of the password. How would you know whether a server has a password using the old method or the new one? Why by a spreadsheet available on the firm-wide-accessible file system, of course! Oh, by the way, there is no server management software.

Critics might say the wizard algorithm has certain disadvantages. The fact that two people, given the same hostname and IP address, often come up with different results for the algorithm. Apparently, writing a script to figure it out for you never dawned on anyone.

Or the fact that when a server has lost contact with the domain and you're trying to log on locally and the phone's ringing and everyone's pressuring you to get it resolved, the last thing you want to be doing is math puzzles.

But at least it's better than the standard way people normally do it!

[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/2018-the-wizard-algorithm


Метки:  

Error'd: A Sour Currency Mix

Пятница, 28 Декабря 2018 г. 14:30 + в цитатник

"Lime bikes are finally in my city! Let's pay for it...So if my USD balance goes below GBP 0 it'll top up with ...AUD?" Ben writes.

 

"I tried to log in to a certain hotel chain's website and noticed this," wrote Gordon S., "I keep clicking the link and it keeps asking if I'm null...so maybe I really am?"

 

"Ths sndz intrstng bt i tnk ill pss. my cding iz gd bt tsting is nt," writes Mike S.

 

Holger K. wrote, "A net income of US $22.1 billion can only be achieved by rigid austerity, like limiting expensive download traffic."

 

"I'm not sure what version of Firefox I'm running, so I should meet these requirements," Jay B. writes.

 

"I was looking for the next train to Milan, but I guess I'll be going to some railway company's intranet instead," Michele.

 

[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/a-sour-currency-mix


Метки:  

Best of…: 2018: Shiny Side Up

Четверг, 27 Декабря 2018 г. 14:30 + в цитатник
It's been many, many years since I've suffered a helldesk gig, but I always get a tickle out of silly helpdesk stories like this one. Always look on the shiny side! -- Remy

CD-ROM

It feels as though disc-based media have always been with us, but the 1990s were when researchers first began harvesting these iridescent creatures from the wild in earnest, pressing data upon them to create the beast known as CD-ROM. Click-and-point adventure games, encyclopedias, choppy full-motion video ... in some cases, ambition far outweighed capability. Advances in technology made the media cheaper and more accessible, often for the worst. There are some US households that still burn America Online 7.0 CDs for fuel.

But we’re not here to delve into the late-90s CD marketing glut. We’re nestling comfortably into the mid-90s, when Internet was too slow and unreliable for anyone to upload installers onto a customer portal and call it a day. Software had to go out on physical media, and it had to be as bug-free as possible before shipping.

Chris, a developer fresh out of college, worked on product catalog database applications that were mailed to customers on CDs. It was a small shop with no Tech Support department, so he and the other developers had to take turns fielding calls from customers having issues with the admittedly awful VB4 installer. It was supposed to launch automatically, but if the auto-play feature was disabled in Windows 95, or the customer canceled the installer pop-up without bothering to read it, Chris or one of his colleagues was likely to hear about it.

And then came the caller who had no clue what Chris meant when he suggested, "Why don't we open up the CD through the file system and launch the installer manually?"

These were the days before remote desktop tools, and the caller wasn't the savviest computer user. Talking him through minimizing his open programs, double-clicking on My Computer, and browsing into the CD drive took Chris over half an hour.

"There's nothing here," the caller said.

So close to the finish line, and yet so far. Chris stifled his exasperation. "What do you mean?"

"I opened the CD like you said, and it's completely empty."

This was new. Chris frowned. "You're definitely looking at the right drive? The one with the shiny little disc icon?"

"Yes, that's the one. It's empty."

Chris' frown deepened. "Then I guess you got a bad copy of the CD. I'm sorry about that! Let me copy down your name and address, and I'll get a new one sent out to you."

The customer provided his mailing address accordingly. Chris finished scribbling it onto a Post-it square. "OK, lemme read that back to—"

"The shiny side is supposed to be turned upwards, right?" the customer blurted. "Like a gramophone record?"

Chris froze, then slapped the mute button before his laughter spilled out over the line. After composing himself, he returned to the call as the model of professionalism. "Actually, it should be shiny-side down."

"Really? Huh. The little icon's lying, then."

"Yeah, I guess it is," Chris replied. "Unfortunately, that's on Microsoft to fix. Let's turn the disc over and try again."

[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/2018-shiny-side-up


Метки:  

Best of…: 2018: JavaScript Centipede

Среда, 26 Декабря 2018 г. 14:30 + в цитатник
As we wind up for the new year, it's time to take stock and look back at some of our best articles for the year. We start with this horrid bit of code, which hopefully has devoured itself since we posted it. --Remy

Starting with the film Saw, in 2004, the “torture porn” genre started to seep into the horror market. Very quickly, filmmakers in that genre learned that they could abandon plot, tension, and common sense, so long as they produced the most disgusting concepts they could think of. The game of one-downsmanship arguably reached its nadir with the conclusion of The Human Centipede trilogy. Yes, they made three of those movies.

This aside into film critique is because Greg found the case of a “JavaScript Centipede”: the refuse from one block of code becomes the input to the next block.

function dynamicallyLoad(win, signature) {
    for (var i = 0; i < this.addList.length; i++) {
        if (window[this.addList[i].object] != null)
            continue;
        var object = win[this.addList[i].object];
        if (this.addList[i].type == 'function' || typeof (object) == 'function') {
            var o = String(object);
            var body = o.substring(o.indexOf('{') + 1, o.lastIndexOf('}'))
                .replace(/\\/g, "\\\\").replace(/\r/g, "\\n")
                .replace(/\n/g, "\\n").replace(/'/g, "\'");
            var params = o.substring(o.indexOf('(') + 1, o.indexOf(')'))
                .replace(/,/g, "','");
            if (params != "")
                params += "','";
            window.eval(String(this.addList[i].object) +
                        "=new Function('" + String(params + body) + "')");
            var c = window[this.addList[i].object];
            if (this.addList[i].type == 'class') {
                for (var j in object.prototype) {
                    var o = String(object.prototype[j]);
                    var body = o.substring(o.indexOf('{') + 1, o.lastIndexOf('}'))
                        .replace(/\\/g, "\\\\").replace(/\r/g, "\\n")
                        .replace(/\n/g, "\\n").replace(/'/g, "\'");
                    var params = o.substring(o.indexOf('(') + 1, o.indexOf(')'))
                        .replace(/,/g, "','");
                    if (params != "")
                        params += "','";
                    window.eval(String(this.addList[i].object) + ".prototype." + j +
                        "=new Function('" + String(params + body) + "')");
                }
                if (object.statics) {
                    window[this.addList[i].object].statics = new Object();
                    for (var j in object.statics) {
                        var obj = object.statics[j];
                        if (typeof (obj) == 'function') {
                            var o = String(obj);
                            var body = o.substring(o.indexOf('{') + 1, o.lastIndexOf('}'))
                                .replace(/\\/g, "\\\\").replace(/\r/g, "\\n")
                                .replace(/\n/g, "\\n").replace(/'/g, "\'");
                            var params = o.substring(o.indexOf('(') + 1, o.indexOf(')'))
                                .replace(/,/g, "','");
                            if (params != "")
                                params += "','";
                            window.eval(String(this.addList[i].object) + ".statics." +
                                j + "=new Function('" + String(params + body) + "')");
                        } else
                            window[this.addList[i].object].statics[j] = obj;
                    }
                }
            }
        } else if (this.addList[i].type == 'image') {
            window[this.addList[i].object] = new Image();
            window[this.addList[i].object].src = object.src;
        } else
            window[this.addList[i].object] = object;
    }
    this.addList.length = 0;
    this.isLoadedArray[signature] = new Date().getTime();
}

I’m not going to explain what this code does, I’m not certain I could. Like a Human Centipede film, you’re best off just being disgusted at the concept on display. If you're not sure why it's bad, just note the eval calls. Don’t think too much about the details.

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

https://thedailywtf.com/articles/2018-javascript-centipede


Метки:  

A Lumpy Christmas

Вторник, 25 Декабря 2018 г. 14:30 + в цитатник

Every "enterprise" shop has that one system you hope you never need to touch. It's older than you are, "documentation" consists of whispers and rumors about its behavior, and it is absolutely 100% business critical. If it goes down, the business goes down.

Fortunately, you'll never have to touch that system, because there's an Ancient Wizard who has been sitting in the same cube since 1973, and knows its secrets. As long as the Wizard is around, you'll never touch it. Of course, if the system goes down when the Wizard is out of the office… well, fixing that would require a Christmas miracle.

Renee was a programmer-elf in Santa's Workshop. It was a huge organization with many layers of middle-elfagent, so 90% of her job was sitting in pointless meetings with no agenda. In the remaining 10%, she occasionally added features to their in-house legal invoice processing software. Since nearly every present they shipped was an elf-produced knockoff of a large company's trademarks, legal billing was one of the Workshop's largest line items.

There were other important IT systems. Supply chain was massive. All raw materials, aside from the naturally-occurring candy canes, had to be imported. Whether it was fabric for producing dolls, or ABS plastic and injection molds for producing dolls action figures. While shipping had a special organizational importance, IT rarely was engaged. The CEC (Chief Executive Claus) had learned to do pivot tables and VLOOKUPs in Excel, and did all his shipment planning himself.

The 100% business-critical mystery system was NNOSE: Naughty/Nice Observation and System Evaluator. It was the "source of truth" for the all important TPS reports: Total Presents Sacked. The Ancient Wizard who cared for it was literally an Ancient Wizard, Merlin. And yes, Merlin really was Santa's sidekick. NNOSE ran on a piece of NORAD surplus computer hardware and was programmed in a dialect of MUMPS nicknamed "Sugar LUMPS" or just "LUMPS". Merlin was the only one who knew how the system worked and what the system did, and Merlin was the only one who was ever supposed to touch it.

As the clock clicked closer to 12/24, the shipping deadline, the Workshop got busier and busier, while software developers got less and less busy. Since time was critical, no software changes went into production unless there was an absolute show-stopping bug. The software teams basically were on an extended break until the New Year, and no code releases would happen until mid-January at the earliest.

So, during the busiest, most critical time of the year, the development team mostly spent their vacation hours. Merlin was out in Avalon, trying to patch things up with his ex. The senior Project Elfagers were on a retreat in Cancun. All through the shop, not a developer was stirring, aside from Renee. Renee loved to work during the quietest time of the year, when no one scheduled any meetings. It was its own kind of vacation…

… at least until Hermie, the lead developer who really wanted to be an MBA, popped his head into her cube.

"NNOSE is down. The Big Guy just tried to pull the final TPS report for the year, and not only did it not have a cover sheet, it printed ten pages of errors instead of data. I've already tried to raise Merlin, but he's not on Slack, and there's no cell service in Avalon."

If the TPS report were wrong or unavailable, Santa couldn't accurately match kids up with presents. Naughty kids could get great gifts, nice ones might get useless garbage like an Amazon Echo or Google Home. He needed that report.

"Okay, but I know the report has been run previously," Renee said. "Can't they just run with an old version?"

"There aren't any old versions. TPSes get shredded after review, ever since GDPR went into effect."

Against her better judgment, Renee set down her hot cocoa and said, "I'll see what I can do."

Merlin didn't keep any digital documentation for NNOSE. Everything about the system was stored in binders full of parchment in his cube. Calling the contents "documentation" would be generous. Merlin had written most of it in High Enochian, and what little bits were in Elvish just seemed to be rants and raves about changes management had requested, and how wrong those changes were. The only system diagram was arranged into an Elder Sign. The most useful thing Renee found in her first pass were post-it notes with login credentials for the various bits.

Still, it was enough for Renee to start piecing together the system. The TPS report came from data managed by NNOSE, but the mainframe-based CLI interface had been abandoned circa 2002. At that point, someone had purchased an expensive mainframe integration package from Initech, which was basically a way of slapping XML/SOAP webservices on top of existing mainframe code. A few years later, someone had slapped together a VB.NET (framework version 1.0) UI which called into that webservice. The VB.NET program actually extracted and printed the report.

Great! Renee kind of knew Visual Basic, or at least could fake it. And it wasn't LUMPS. She started by testing the NNOSE XML interface- she sent a few SOAP requests manually and verified that she got correct output. Then she fired up the VB.NET app. It had a basic UI for setting filters and criteria, but once you hit "run report", everything—even the error messages—went to the printer. Worse, you couldn't tell it what printer to use. Every print went to one printer down in the reindeer stables.

Cue the testing cycle of "try running the report, ride the world's slowest elevator to the basement, walk through the reindeer stables, wait for the printer to finish running off its pages of error messages, drag the ream of paper back upstairs and try to match it to the code." Through this process, Renee learned a few important things. First, no matter how Christmas-y and magical reindeer were in spirit, in odor they were more Halloween Horror. Second, for some reason, there were SQL errors showing up in the stack traces. But everything was supposed to be webservices wrapped on mainframes, so why were there database calls?

Renee went back to Merlin's binders, and with the help of what little High Enochian she could remember from high school, Renee started to piece together what was happening.

Circa 2004, against Merlin's protests, there had been a project code-named RED. The goal of RED was to "upgrade" NNOSE to a full J2EE system with an Oracle backend. If Renee was reading the Enochian correctly, Merlin had banished the elf responsible for contracting the vendor to the Astral Plane, where they were surely captured by Githyanki.

"Well, that's got to be a violation of HR policies," Renee noted to herself.

The project never completed, but progressed to the point where the Oracle backend had been running in parallel with NNOSE ever since. That explained the SQL errors. The VB.NET app had functionality added to talk to the "upgraded" RED system. At some point in its history, the VB.NET app had been pointed to that backend, and had been querying it instead of the mainframe. Sure enough, when Renee logged into Oracle directly, most commands returned errors as something in this more-or-less unmaintained and unpatched Oracle instance was completely FUBAR.

Renee poked at the VB.NET app until she figured out how to resurrect the webservice-based data access layer. One more olfactory offense later, and Renee was holding a TPS report. Off it went to Santa, and off she went to give an after action to Hermie.

"Great work! You've saved Christmas!" Hermie said. "Shame about Merlin, though."

"What about Merlin?"

"Oh, the whole banishing poor Roger to be soulsucked on the Astral Plane. That is absolutely a firing offense, and we're going to have to let Merlin go. Don't worry, though. After this, I'm confident that you can fill in as our new NNOSE and LUMPS expert. You can think of it like a promotion, and maybe in a few years, it'll involve a salary increase!"

[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-lumpy-christmas


Метки:  

Classic WTF: Power Supply

Понедельник, 24 Декабря 2018 г. 14:30 + в цитатник
It's Christmas Eve, and as per usual, we're taking the day off. As you're thinking about your gifts, think about unwrapping THIS present, from a few years back. Original. -- Remy

MRI scans, while neat, do leave something to be desired in the “fun” and “comfort” departments. After surrendering every sliver of metal and some percentage of clothing, the patient must sit or lie stock-still in a cold room for long stretches of time. As the giant magnets do their work, ear-splitting tones and rhythmic pulses fill the room. For those who lie down to enter the giant magnet-coffin, it’s easy to feel like the Frankenstein monster in some mad scientist’s German techno experiment.

The noise is so bad that most facilities issue earplugs to their patients- but some, as Evi relates, spring for $1,500 headsets, and $10,000 systems to play music through said headsets. Seem steep? No doubt the 1–3 year warranties, ranging from $1,500 to $3,500, raise eyebrows too- but it was well outside the warranty period that Evi learned the true extent of the fleecing.

The power supply for the headphone system had failed. When Evi called the company for help, they claimed they couldn’t possibly repair the system, but would be happy to send a new power supply- for $1,500. Taking matters into his own hands, Evi used a multimeter to determine that only the 9V voltage output was nonfunctional. He readied his soldering iron and opened up the case, expecting to replace a 7809 chip and call it a day. Instead, he found…

Four cheap Chinese power supplies- one for each voltage the power supply was supposed to output- hot-glued together.

Evi ordered a new power supply from Amazon, and hot-glued it into place. Total cost? $10.

[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/classic-wtf-power-supply


Метки:  

Error'd: A Generic Holiday Title Goes Here

Пятница, 21 Декабря 2018 г. 14:30 + в цитатник

"Sure, there's the obvious 'they didn't put any effort into the email subject,' but the placeholder kind of shows they didn't intend to in the first place," Chris wrote.

 

"I figure I had a 50/50 chance of downloading my driver from Xerox's site," writes Greg A., "I just hope they're not randomizing the order of the buttons on every reload."

 

"Obviously, there's a definition of 'California topography' out there that I'm not familiar with," Mike S. wrote.

 

Randal S. writes, "Yes, I would like to meet someone new in (null)! Thank you, match.com!"

 

"Ok Yelp - I guess if I knew pictures I didn't take were so popular, I'd not take any pictures more often?" wrote Roger G.

 

"First, I was having trouble ordering with any of my credit cards, and then I had trouble ordering anything with my timestamp," wrote Cameron H.

 

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

https://thedailywtf.com/articles/a-generic-holiday-title-goes-here


Метки:  

Representative Line: Explicitly True

Четверг, 20 Декабря 2018 г. 14:30 + в цитатник

Part of Python’s appeal is its rich class library. The old XKCD about import antigravity sometimes doesn’t feel that far off. Combined with a few third-party libraries, like NumPy, you can do a lot with very little code.

Of course, that feels a bit like magic. As Python gurus like to say, “Explicit is better than implicit”. One of Mark’s co-workers took this perhaps a bit too far, when they started adding this import to every file:

from __builtin__ import True

As you might imagine from a name like __builtin__, everything in that namespace, including True, is imported by default. Mark found this “among other useless stuff”. One has to wonder: how much useless stuff.

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

https://thedailywtf.com/articles/explicitly-true


Метки:  

Assumptions are the Mother of all Bugs

Среда, 19 Декабря 2018 г. 14:30 + в цитатник

A long time ago in my "C" programming days, I learned that when you code up anything that depends on any sort of external data, be it a file, database or socket, you should be paranoid and do it defensively. After all, you can't control those things and there's no guarantee that they will always work the way you hope. Sometimes you care about every possible error code; sometimes just success or failure. The point is to check the result of what you tried to do.

Fast forward through several years of C++ and ten years into Java, and our boss calls us into the office.

The Command Controller application is failing and nobody knows why. It runs fine for a while and then it starts throwing what appear to be random exceptions. The problem is happening on almost every single command that it's receiving, but only in production. We can not reproduce the issue in any of the other environments (DR, pre-prod, QA or Dev). The team that wrote it is dumbfounded and has asked for help. We have a pretty good reputation at solving tough issues, so you guys need to drop everything and figure this out.

Normally, the first step would be to attach a debugger and see where it's going ker-flooie. Nope: you aren't allowed to do that in production - ever, no exceptions!

Well if it can't be reproduced anywhere else, how are we going to do it? We will use truss, reasoning that we could capture the output, walk through it against the source code and try and match up all the I/O calls. It's painful, but doable.

As you might imagine, this generated quite a large log file. After fourteen long hours, we finally spotted the problem:

   try {
        byte []buffer = new byte[8192];
        bufferedInputStream.read(buffer);
        // Use buffer
    } catch (Exception e) {
        // ...
    }

Something clicked from decades in the past; make sure you got the number of bytes you intended to read!

But why would this suddenly start to fail? Something had to have changed! This code hadn't changed for several years, and nothing had been deployed for three months! After asking around the data center, it turned out that some SA had applied a routine OS-patch, which awakened this sleeping gremlin. To check it, we ran the unmodified binary on an unpatched machine and sure enough, the problem disappeared.

Since rolling back the OS patch in production was never going to happen at 3AM, we wound up grepping through every line of code of that application and replacing all of the single-line socket-reads with the proper loop, with appropriate error checking:

    int COMMAND_BUF_SIZE = 8192; // loaded from a property file
    byte []buffer = new byte[COMMAND_BUF_SIZE];
    int totalBytesRead = 0;
    try {
        while (totalBytesRead < buffer.length) {
            int numBytesReadThisTime = bufferedInputStream.read(buffer,totalBytesRead,buffer.length - totalBytesRead);
            if (numBytesReadThisTime == -1) {
                break; // Unexpected end-of-stream
            }
            totalBytesRead += numBytesReadThisTime;
        }
    } catch (final Exception e) {
        // Handle read-error
    }
    if (totalBytesRead < COMMAND_BUF_SIZE) {
        // throw exception for unexpected EOF
    }
    // Use buffer

Then all we had to do was the manual build and deployment at 5AM.

At 6AM, we all went out for breakfast. At 7:30, we came back to grab our stuff and go home. That's when the other managers in the department pointed out that there was work to do. That's when we pointed out that while they were in slumberland, we had been at it all night long and it was time for us to go nite-nite. Then we left.

[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/assumptions-are-the-mother-of-all-bugs


Метки:  

CodeSOD: Trim the Tree

Вторник, 18 Декабря 2018 г. 14:30 + в цитатник

Tis the season to think of trees.

Our Anonymous submitter has a program with a tree in it, and it’s a relatively big one: 7 levels deep, with 200,000 leaf nodes. Oh, and it’s managed in client-side JavaScript. In other words, it’s the sort of thing you really want to make sure you’re accessing efficiently.

Since it’s a tree, and since in this case, all the nodes are doubly linked (each child contains a reference to its parent), it’s easy to get from any one node to any other, with a minimal number of steps. There’s never a good reason to traverse the entire tree.

Which is why Anonymous facepalmed when they found this code:

function matchWidget(root, widget, folder) {
  if (root.items) {
    root.items.forEach(item => {
      if (item.type === 'widget') {
        if (item.id === widget.id && item.parent.id === widget.parent.id ) {
          item.processed = true;
          updateParentCounters(item, folder);
        }
      }
      if (item.items) {
        return matchWidget(item, widget, folder);
      }
    });
    return matchWidget(root.items, widget, folder);
  }
  return root;
}

The purpose of this code is that as an item is “processed” in this application, the counter on all its ancestor nodes has to be incremented. There’s a handy method already written for doing that, called updateParentCounters, which walks up the tree to the root node following the parent reference on each node.

That’s not what this code does, of course. This code starts at the top of the tree. It looks at each possible root node (root is not a tree node, it’s an object with an items property, and each of those is a root node for a different tree). It’ll recursively walk down the tree, visiting every node. When it finds the node it’s looking for, the recursion stops and it then calls updateParentCounters. The loop doesn't stop, so it'll search the other elements in root.items anyway.

The problem, of course, is that it already has the item it’s looking for- widget is the item it wants. So the entire tree search can be replaced with updateParentCounters(item, folder). Which is exactly what our anonymous submitter did, vastly improving the performance of the application.

[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/trim-the-tree


Метки:  

CodeSOD: A Short Leap

Понедельник, 17 Декабря 2018 г. 14:30 + в цитатник

You know the story. A report is spitting out the wrong dates. Someone gets called in to investigate what’s wrong. After digging through piles of deeply nested SQL queries and views and trying to track down the problem, it turns out someone wrote their own date handling code which is wrong.

Darin P found the code this time.

SET @EDate = (SELECT CAST(CAST(CASE WHEN MONTH(GETDATE())-1 = 0 THEN 12 ELSE MONTH(GETDATE())-1 END AS NVARCHAR) 
	+ '/' +
	CASE WHEN MONTH(GETDATE())-1 = 2 THEN '28'
	WHEN MONTH(GETDATE())-1 = 4 THEN '30'
	WHEN MONTH(GETDATE())-1 = 6 THEN '30'
	WHEN MONTH(GETDATE())-1 = 9 THEN '30'
	WHEN MONTH(GETDATE())-1 = 11 THEN '30'
	ELSE '31'
	END
	+ '/' + CAST(CASE WHEN MONTH(GETDATE())-1 = 0 THEN YEAR(GETDATE())-1 ELSE YEAR(GETDATE()) END AS NVARCHAR(50)) AS DATETIME))

I don’t want to leap to any conclusions, but I think this code does a bad job of calculating how many days are in a given month. Hopefully they fix it before 2020.

[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-short-leap


Метки:  

Error'd: Trouble at the End of the World

Пятница, 14 Декабря 2018 г. 14:30 + в цитатник

"Normally, the solar face in Apple Watch, is supposed to show a single 24-hour period," writes Juan C. wrote, "It turns out that going to Ushuaia (the southernmost city in the world) makes it a bit confused, specifically stating that noon is midnight and showing more than one day."

 

Wow...Patreon is feeling VERY thankful this time of year," wrote Guillermo.

 

"I understand that XML parsing is not everyone's cup of tea but outright stating that it's not OK is a bit harsh.," writes Martin E.

 

"I went to the website and tried to prepay for next year, and the prepay price was exactly $58.26 more than twelve regular monthly payments!" Louise H. writes.

 

Tobias writes, "This is why they say "when you use undefined behaviour in C, the code can do anything"...Like making code that would require the death of many universes to finish running return the result almost instantly."

 

"I was trying to complain about some noise, but now I have a buzzing in my head," Jack B. wrote.

 

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

https://thedailywtf.com/articles/trouble-at-the-end-of-the-world


Метки:  

Politics Rules! Common Sense Drools!

Четверг, 13 Декабря 2018 г. 14:30 + в цитатник

As programmers, we all need to fix bugs. As experienced programmers, we recognize that sometimes, the ability to fix one bug depends upon first fixing another bug. Managers, on the other hand, don't always get that simple concept.

At the beginning of my career, I worked for Initrode where I wrote software to run a test-station that diagnosed assorted electronic components of jet fighters. Initrode acted as a government-supplier of the test station to another government contractor (LUserCorp) that used the station to write the test sequences to diagnose electrical faults. If the test station hardware malfunctioned, or there were bugs in the software that made the electronics tests fail to work properly, then LUserCorp could use that as an excuse for time and cost overruns. If that happened, then the government would penalize Initrode to recoup those costs.

Over time and several releases of the hardware and software, a series of hardware faults and software bugs managed to creep into the system. Since LUserCorp was running behind schedule anyway, they decided that they'd use this as an excuse to hit the government for more time and money. Naturally, the brass at Initrode fought back because they didn't want to take the financial hit.

After lots of political back-and-forth, an official prioritized bug list was created, and it was mandated by LUserCorp that the bugs had to be fixed in the order in which they appeared on the list.

To this end, me and another junior developer were sent to LUserCorp to act as a Tiger Team. Basically, this means we are in a locked room, alone with the test station. The LUserCorp people were not allowed in the room with us. We brought the source code on our own disk pack which one of us had to be with at all times. This meant that if we went to lunch, or both had to hit the restroom at the same time, we had to power everything down and take the disk with us.

The list of bugs to be addressed was provided to us only after we were on site. The first and most important bug on the list was something I had coded that had an off-by-one error in a nested loop, that only appeared at the end of the third iteration of the outer loop. Since each inner loop processed and printed the 6-line result of each of 4K tests (to a very slow thermal printer), it took 6 hours to print out 3*4K*6 => 72K lines of test results.

Our software also had stop-at-test-n functionality. We noticed that bug number 2 on the list was in the stop-at-test-n functionality (it prevented that feature from being used).

In the ideal case where all other functions were working, we'd do:

  • turn off printing
  • set stop-at-test to: 12K-1
  • start running tests (it would finish in a few seconds)
  • turn on printing
  • set stop-at-test to: 12K+2
  • start running tests
  • look at 20 lines of output and see what was wrong

Naturally, we called Initrode and asked for permission to fix bug 2 before bug 1. Initrode called LUserCorp who flat out said No! Even after we explained that it would save oodles of time. NO; the bugs MUST be fixed in the specified order!

So for days, we would make a code change, compile for 5 minutes, launch the test sequence and goof off for 6 hours while waiting for it to print out 1200 pages of garbage before getting to the one test result we needed to see.

Once we figured out and fixed the problem of bug 1, we then spent the rest of our time there fixing the remainder of the bugs on the list, but were under strict orders NOT to divulge that we had fixed anything beyond bug 1.

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

https://thedailywtf.com/articles/politics-rules-common-sense-drools


Метки:  

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