Friday, March 29, 2019

Error'd: Out of Order

"Considering the format died out a decade ago, I think I'm going to remove this one from my list and pass on the pre-order," John C. writes.

 

"Thanks to Bing, today I learned of the importance of International Women's Day in the Russian Revolutions," writes Andy M.

 

Niklas K. wrote, "Ever have that feeling that you possibly left your stove on and went all the way back home just to make sure? Well, I think my train did that too."

 

"It's too bad the green beans aren't available, I guess I'll just have to try the green beans instead," James wrote.

 

Pascal writes, "Logged in before I signed up? Now that's what I call predictive!"

 

Rob wrote, "The 'Contact Us' and 'FAQ' pages with equally angulared ng-ng-ng."

 

[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.


To read the full article, please visit The Daily WTF

Thursday, March 28, 2019

150 Year Old Lost Wedding Dress Found

Choosing wedding attire requires a lot of time and brainstorming. However, one of the tiny ensembles used at this occasion which are better known as the flower girls dresses also deserve a great deal of attention just like the wedding gown. Pick the flower girls dresses syncing with the party theme This means if you are […]

The post 150 Year Old Lost Wedding Dress Found appeared first on Viral Viral Videos.



To read the full article, please visit Viral Viral Videos

The Blanking Blank

Since the dawn of software development, people have endlessly been searching for a way to modularize their applications efficiently. From the “do one thing and do it well (and also everything is text)” protocols of Unix-style command line tools, through to modern microservices, the key idea has always been to have simple, easy to understand components which interface in simple, easy to understand ways. Complex things are built from piles of small, tiny things.

Matt W was working on one of those simple modules in a Big Complicated Thing. The Big Complicated Thing was an enterprise “do everything” tool, and like most enterprise tools, it was larger and more complicated than it needed to be. Also, everything talked to everything else in XML, the most enterprise of cross-component interfaces.

Over the decades of continuous development, components had proliferated, interfaces had ball-of-mudded together, and seemingly arbitrary silos created boundaries where they didn’t make any sense. To wit, Matt needed to build a report out of the contents of some server-side session variables. Those session variables were populated by another component, which fetched the data from yet another component. Worse, many of those variables were optional, but despite using XML much of the data was stringly typed. Which meant, during testing, Matt saw this in a report:

Bill Lumbergh, null for Initech

Matt’s code dutifully checked for empty strings and actually null strings, but hadn’t been prepared for a "null". On a null or empty job title string, the code should output, “Bill Lumbergh, with Initech”. Matt didn’t particularly want to add that check to his code, since the data should be clean by the time he got it.

Matt chatted up Cecil, the developer who maintained the component that populated the session variables.

“Hey, could you do me a favor?” Matt asked. “If something comes through as the string ‘null’, could you make it blank?”

“Oh, yeah, no problem,” Cecil said. “I’ll roll that out later today.”

A few hours later, Matt grabbed the latest build and re-ran his test, confirming that Cecil had done exactly what he asked.

Bill Lumbergh, blank for Initech.

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


To read the full article, please visit The Daily WTF

Wednesday, March 27, 2019

Announcements: Who's up for a scotch at InedoCon in Portland?

A couple weeks back, I posted the Free Mug Day campaign: run through the quick BuildMaster tutorial, and I'll send you a free mug. Today, I have a slightly different offer: meet me at InedoCon (Portland, May 22/23) as a TWDTF delegate, and let's chat software over scotch!

Why Portland? As part of the mug campaign, I asked everyone to share their feedback/comments/advice, and I got lots of suggestions on how we can improve the software itself. That was great, and then I saw this:

TRWTF is that I had no idea what BuildMaster actually did until now. I've seen it advertised for years, I even went to your website once or twice, but I figured it had something to do with builds and didn't really care. Anyway, I was desperate for a free mug and just gave it a try...

Well, turns out I was wrong. It's a damn useful tool and I've going to start using it to replace our existing deployment tool disaster. I guess, my main advice... perhaps say what BuildMaster actually does? We could have used this years ago. Though I wouldn't have gotten my free mug...

This wasn't the first time I've heard this sort of feedback. I originally designed BuildMaster to be very flexible, and to solve all sorts of different problems in software delivery. For a lot of customers, it did exactly that.

"Something" is better than "Everything"

Over the years, I'd proudly proclaim that "BuildMaster can do everything!" Turns out that "doing everything" may as well mean "doing nothing", and that's a problem when you're trying to sell a product. It has to "do something", and that something is called a product story. It's taken me a long time to understand that, and I learned a lot of it from TDWTF readers like you.

I'm confident my heart is in the right place. Ten years ago, I wrote that Programming Sucks! Or At Least, It Ought To, and I still believe that developers should work closely with business stakeholders to solve business problems with code. That's my vision of BuildMaster, and the other products I designed at Inedo.

Who's up for a scotch... in Portland?

If you share this vision, I'd would love to buy you a scotch and get your opinion on how we can better communicate this to the world. We're hosting our first-even user conference in Portland, and I'll be talking about how unnecessary complexity that's masquerading as innovation is stifling actual innovation.

Some of our very enthusiastic customers (and fellow TDWTF readers) will be share how they navigated this complexity, improved the lives of developers, and helped their organization as a whole:

•   WebMD's Continuous Delivery Architect, Aaron Jensen will talk about how they successfully transitioned from a monolith application with no automation to a CI/CD platform with dozens of microservices using BuildMaster

•   Robert Vandehey, Alkami's Vice President and Chief Architect, will show how they componentized a monolith into packages for microservices using ProGet as the key link in their deployment chain

•   BuildMaster's product director John Rasch will demonstrate how you can add CI/CD to a legacy application through build, deployment, and process automation.

•   Governmental organizations and other compliant-heavy industries have specific challenges for automation. Jody Dorchester will present how 100's of applications were automated with BuildMaster in less than a year, while maintaining compliance.

Even if you don't use Inedo's tools --- heck, especially if you don't use Inedo's tools --- the lessons we share will be helpful for you, and the outsider insights you have will be invaluable for everyone.

I've got three complimentary tickets for those who are interested, and a single travel voucher to cover your flight and hotel. Just fill out this form before 2019/Apr/5, and we'll be in touch.

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


To read the full article, please visit The Daily WTF

CodeSOD: This Is Your Brain on PL/SQL

The realest of real WTFs, the reigning champion for all eternity is and forever will be Oracle. Today, we’re going to take a look at a little code in PL/SQL.

PL/SQL is a weird language, a blend of SQL and, well, a Procedural Language, with a side of OO slapped on. The syntax does an excellent job giving you the feeling that it was designed in the 1970s, and each new feature or change to the language continues that tradition.

The structure of any PL/SQL code unit is going to be built around blocks. Each block represents a self-contained namespace. The basic anatomy is:

DECLARE
  -- variable declarations go here
BEGIN
  -- code goes here
EXCEPTIONS
  -- exception handling code goes here, using WHEN clauses
END;

If you’re writing a stored procedure, or a trigger, you replace the DECLARE keyword with CREATE [OR REPLACE]. You can also nest blocks inside of other blocks, so it’s not uncommon to see code structured like this:

BEGIN
  DECLARE
    --stuff
  BEGIN
    --actions
  END;
  --more actions
END;

Yes, that does get confusing very quickly. And yes, if you want to really approximate structured error handling, you have to start nesting blocks inside of each other.

The language and database have other fun quirks. They didn’t get an IDENTITY column type until version 12c. In prior versions, you needed to use a SEQUENCE object and write procedures or triggers to actually force the autonumbering. You’d usually use a SELECT INTO… statement to populate a variable, with the bonus that Oracle SQL always requires a table in the FROM clause, so you have to use the made up table dual, e.g.:

CREATE TRIGGER "SOME_TABLE_AUTONUMBER"
BEFORE INSERT ON "SOME_TABLE"
FOR EACH ROW
BEGIN
  SELECT myseq.nextval INTO :new.id FROM dual;
END;

:new in this context represents the row we’re autonumbering. That’s the “normal” way to create autonumbered columns in older versions of Oracle. Boneist found a different, slightly less normal way to do the same thing:

CREATE OR REPLACE TRIGGER "SCHEMA1"."TABLE1_TRIGGER"
  BEFORE INSERT ON "SCHEMA1"."TABLE1"
  FOR EACH ROW
BEGIN
  DECLARE
    pl_error_id table1.error_id%TYPE;
    CURSOR get_seq IS
        SELECT table1_seq.nextval
        FROM   dual;
  BEGIN
    OPEN get_seq;
    FETCH get_seq
        INTO pl_error_id;
    IF get_seq%NOTFOUND
    THEN
        raise_application_error(-20001, 'Sequence TABLE1_SEQ does not exist');
        CLOSE get_seq;
    END IF;
    CLOSE get_seq;
    :new.error_id := pl_error_id;
  END;
END table1_trigger;

There’s a lot going on here. First off, note that our DECLARE section contains a CURSOR statement. Cursors let you iterate across records. They’re very expensive, and in Oracle-land, they’re a resource that must be released.

This trigger uses a nested block for no particular reason. It also uses an extra variable, pl_error_id which isn’t necessary.

But the real weird part here is the IF get_seq%NOTFOUND block. That’s pretty simple: if our cursor didn’t return a row. This is something that, with this cursor, can’t possibly happen, so we’ll never hit this. The sequence will always return a value. That’s a good thing, if you look at the code which follows.

raise_application_error is Oracle’s “throw” equivalent. It will crawl up the stack of executing blocks until it finds an EXCEPTIONS section to handle the error. Note that we close the cursor after that statement- thus, we never actually close the cursor. Cursors, as mentioned, are expensive, and Oracle only lets you have so many of them.

Here we have a weird case of a developer defending against an error that can’t happen in a way which would eventually lead to more errors.

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


To read the full article, please visit The Daily WTF

Tuesday, March 26, 2019

CodeSOD: Doubly Encrypted Logins

Providing authentication for your web-based APIs is both a challenging problem but also a largely solved problem. The hardest part is really just working your way through the various options, and from there it’s usually some variation on a drop-in component.

Done properly, it’s also client-agnostic. I can access the service from my browser, I can access it from a thick client, I can access it from cURL. Done incorrectly, well, you get what happened to Amira.

She was trying to pull some statistics from the backend, and couldn’t figure out how to authenticate. So she checked the front-end code to see how it authenticated:

crypt = new JSEncrypt();
crypt.setPublicKey('<removed>');
challenge = "<removed>";
function doChallengeResponse()
{
document.loginForm.password.value.replace(/&/g, '%26');
document.loginForm.password.value.replace(/\\+/g, '%2B');
document.loginForm.password.value = crypt.encrypt(document.loginForm.password.value);
document.loginForm.response.value = document.loginForm.password.value;
document.loginForm.password.value = '';
document.loginForm.submit();
}

On one hand, I want to guess that this code is very old, just based on the document.loginForm approach to interacting with DOM elements. On the other, JSEncrypt was first released in 2013, setting an upper limit on the age.

We send those credentials to the backend using a from submission, which our original developer decided needed some sanitization- all the & and + in the password are escaped, which… shouldn’t be necessary because the form should be doing a POST request, but also, we’ve encrypted the data.

Here’s my suspicion. This code is actually quite old. The original developer copied it from a circa 2005 StackOverflow post, and it didn’t include things like encryption or sending the form as a POST. Over the years, little things got added to it, one after the other, but the core mechanics never really changed.

Amira did check the history, and found that the previous version didn’t use encryption, and instead concatenated the password with the challenge variable, MD5 hashed the two, and sent that over the wire, which… well, almost kinda works, if you don't think about it too hard.

The good news is that once Amira figured out how to get the cookie she needed, the server never expires that token, so she’s free to keep it, send her requests via cURL, and never look at the web form again. She doesn’t have to worry about the cookie being compromised in transit, because the application uses and has always used SSL/TLS.

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


To read the full article, please visit The Daily WTF

Monday, March 25, 2019

It's The End Of The Month As We Know It

Calendario abril-junio 2008

If you ask an engineer whether it's safe to cross a bridge, he'll happily walk you through how safe bridges are, how the mathematics work out, how far we've come in structural safety. You'll come away from the conversation feeling confident that no bridge will ever collapse anywhere on the face of the Earth. If you ask a software engineer about banks, however, you'll likely come away terrified, with a 50/50 chance you're now convinced to put all your money in bitcoin. Banks are notorious for bad software decisions—not so much because the decisions are worse, but because most people assume banks are more careful and security-minded.

Today's submitter, Kato, worked at Inibank, where they used a commercial product called T24 as the core of their banking system. T24 is used by hundreds of banks worldwide. It's customizable for a wide range of banking solutions, and so like most large customizable suites, there are programmers that specialize in writing custom code for it and consultants that will hold your hand through major upgrades.

Inibank brought in a consultant to take on a special project while their resources were busy. At the end of the business day, there is a Close Of Business process that has to be done to ensure all the money gets where it's going, all the appropriate outputs are recalculated, and all the relevant reports are run. In banks, this also changes the system's date to the next working day—which is why if you do online banking on a Sunday, none of it begins to process until Monday morning. The consultant was meant to create a new report that would run during the Close Of Business process, which would do extra processing if it were also the End of Month.

Kato sat down with the new guy, showing him how they'd set up their end of day reports. "You see here, there's a global for the last working day, one for today, and one for the next working day. Those are YYMMDD, so they're easier to work with."

"Right, right okay, gotcha. Gotcha. And what format is that?"

"... I don't know the standard off the top of my head, but it's year, month, day."

"Right, right, okay. Cool. I'll get right to work, then."

Kato walked away from the conversation with a sinking feeling in the pit of his stomach, but he tried to ignore it. The consultant said he was all set up and ready. Surely he knew what he was doing, right? Kato put it out of his mind, and didn't worry about it again until it came time to review the code, and he found this gem:

TH.DATE = R.DATES(EB.DAT.NEXT.WORKING.DAY)[1,6]:"01"
CALL CDT('ES00',TH.DATE,"-1C")
WTODAY = OCONV(DATE(),"DY") : FMT(OCONV(DATE(),"DM"),'R%2') : FMT(OCONV(DATE(),"DD"),'R%2')
IF TH.DATE EQ WTODAY THEN


In layman's terms:

  1. Take the next working day and change the day to 01 in order to get the first day of the month.
  2. Change that date by subtracting 1 calendar day, in the Spain calendar.
  3. Take the server's date and put in format YYYYMMDD by calling 3 times for the command Date.
  4. If the date calculated in step 2 is the same as the date calculated in step 3, run the process.

Now, this ... works. Mostly. Except that if for some reason close of day ticked over past midnight on the second-to-last day of the month—not uncommon—it would incorrectly think it was the last day of the month and run the report. Which worked well with the next problem: if the same thing happened on the last day of the month, it would incorrectly not run the report. And the best bug yet: if the last day of the month was a Sunday, the server's calendar would never be set to it, since it skips non-working days.

Speaking of non-working days: as Inibank was US-based, there was no reason to use the Spain calendar. Sure, your months and weeks are the same, but the US bank holidays would need to be set in the Spain calendar in the software, or else it would still run. Finally, as if all this weren't bad enough, calling for the Date three times meant you could have inconsistencies if it straddled midnight exactly: the month retrieved before midnight, the day after.

Kato put in a comment, suggesting that the code be changed to:

IF R.DATES(EB.DAT.TODAY)[5,2] # R.DATES(EB.DAT.LAST.WORKING.DAY)[5,2] THEN


Five minutes later, the contractor was at his desk. "What is this change?"

Kato was in no mood to argue by this point. "Your code's broken, dude. You didn't need to do all that."

"I see, I see. Well, it's just, this is the standard operating procedure in the industry. But no matter."

Kato highly doubted this, but he shrugged it off. "Industry's wrong, then. I explained it all in the comment."

"I see. Yes, I read this. But I will read it again." And then he was gone, as suddenly as he'd appeared at Kato's desk.

The edits were made, Kato approved the PR, and the consultant vanished into the night.

Sometimes, late at night, Kato lies awake wondering if the consultant really understood what he did wrong, or if he were just paying lip service, collecting his check, and writing terrible code for twice Kato's salary somewhere else. Somewhere without in-house staff to look over the code.

But don't put all your money in bitcoin. That's even worse.

[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.


To read the full article, please visit The Daily WTF

Friday, March 22, 2019

Error'd: Killer Errors

Adam wrote, "I hear that NewFeature1 is a real, ahem, killer feature of these Wi-Fi drivers."

 

"Gigabyte Easy Tune6 installer must release to the failure! There is no other option!" writes Jeff B.

 

"DPD is having a really hard time guessing which month my Ebay delivery will take place," Rupert W. writes.

 

"So this USB expander can power all my peripherals, an old timey typewriter, AND a fan? Sold."

 

"My wife is flying from Chicago to Atlanta and had to reschedule," Casey B. wrote, "Luckily, she'll arrive almost two days before she leaves."

 

Chris D. writes, "So is this like malware credit? Can I run a couple of thousand malicious programs before I need to worry about infection?"

 

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


To read the full article, please visit The Daily WTF

Thursday, March 21, 2019

CodeSOD: Swing and You're Out

George G was hired to do some UI work for a company which sold a suite of networking hardware. As networking hardware needs to be highly configurable, George was hired on to do “some minor tweaks” to the UI. “It’s just some sizing issues, fonts, the like. I’m sure you’ll do something to the stylesheets or whatever,” said the boss.

The boss didn’t know what they were talking about. The UI for some of the products was a web based config tool. That was their consumer-grade products. Their professional grade products used the same Java program which was originally released 15 years earlier. There were no stylesheets. Instead, there was an ancient and wobbling pile of Java Swing UI code, maintained by a “master” who had Strong Opinions™ about how that code should look.

For example, dispatching a call to a method is indirection. Indirection is confusing. So inline those calls, especially if there's a conditional involved: inline all the “ifs”. Factory methods and other tools for constructing complex objects are confusing, so always inline your calls to constructors, and always pass as many parameters as you can, except for the times where you don’t do that, because why would we be consistent about anything?

All of the developers on the project had to attend to the master’s wishes during code reviews, where the master gleefully unrefactored code “to make it more clear.”

Also, keep in mind that this UI started back in an era where “800x600” was a viable screen resolution, and in fact, that’s the resolution it was designed against. On a modern monitor, it’s painfully tiny, stuffed with tabs and icons and other UI widgets. Over the years, the UI code has been tweaked to handle edge cases: one customer had the UI zoom turned on, so now there were piles of conditionals to check if the UI needed to be re-laid out. Somebody got a HiDPI display, so again, a bunch of checks and custom code paths, all piled together.

Speaking of layout, Swing was a prime case of Java taking object orientation to the extreme, so in addition to passing in widgets you want displayed, you also can supply a layout object which decides how to fill the frame. There was a whole library of them, but if you wanted a flexible layout that also handled screen scaling well, you had to use the most complicated one: Grid Bag. The Grid Bag, as the name implies, is a grid, but where the grid cells can be arbitrary sizes. You control this by adding constraints to the flow. It’s peak Java overcomplification, so even simple UIs tend to get convoluted, and with the “inline all the things” logic, you end up with code like this:

if( os.getSystemFontSize( NORMAL ) == 14 )
text = new JText("5", new GridBagConstraints(3, 1, 3,3, 1.0, 0.5, GridBagConstraints.PAGE_END, 1.5, Insets(10,5,10,5, 5, 5 ) );
else   
text = new JText("5", new GridBagConstraints(3, 1, 3,3, 0.99, 0.4, GridBagConstraints.PAGE_END, 1.5, Insets(4,2,4,5, 5, 5  ) );

This particular code checks to see if the user has their font set to 14pt. If they do, we’ll set a constraint one way. If it’s any other value, we’ll set the constraint a different way. What is the expected result of that constraint? Why all this just to display the number 5? There are a lot of numbers other than 14, and they’re all going to impact the layout of the screen.

George made it two months, and then quit. This happened just a week after another developer had quit. Another quit a week later. No one in the management chain could understand why they were losing developers so quickly, with only the master remaining behind.

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


To read the full article, please visit The Daily WTF

Wednesday, March 20, 2019

CodeSOD: Remove This

Denae inherited some 90s-era GUI code. The original developers have long since gone away, and the source control history has vanished into oblivion. In the 90s, the Standard Template Library for C++ was still very new, so when Denae needs to debug things in this application, it means doing some code archaeology and picking through home-brewed implementations of common data structures.

Denae’s most recent bug involved understanding why some UI elements weren’t updating properly. The basic logic the application used is that it maintained a List of GUI items which need to be repainted. So Denae dug into the the List implementation.

template <class Type> void List<Type>::Remove(Type t)
{
        int i;
        for (i=(num-1); i>=0; i--)
        {
                if(element[i] == t)
                {
                        break;
                }
        }
        LoudAssert(i>=0);
        DelIndex(i);
}

template <class Type> void List<Type>::DelIndex(int i)
{
        LoudAssert(i<num);
        num--;
        while(i<num)
        {
                element[i] = element[i+1];
                i++;
        }
}

Let’s start by talking about LoudAssert. Denae didn’t provide the implementation, but had this to say:

LoudAssert is an internally defined assert that is really just an fprintf to stderr. In our system stderr is silenced, always, so these asserts do nothing.

LoudAssert isn’t an assert, in any meaningful way. It’s a logging method which also doesn’t log in production. Which means there’s nothing that stops the Remove method from getting a negative index to remove- since it loops backwards- and passing it over to DelIndex. If you try and remove an item which isn’t in the list, that’s exactly what happens. And note how num, the number of items in the list, gets decremented anyway.

Denae noticed that this must be the source of the misbehaving UI updates when the debugger told her that the list of items contained -8 entries. She adds:

We have no idea how this ever worked, or what might be affected by fixing it, but it’s been running this way for over 20 years

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


To read the full article, please visit The Daily WTF

Tuesday, March 19, 2019

Exceptionally Serial

You may remember Kara, who recently found some "interesting" serialization code. Now, this code happens to be responsible for sending commands to pieces of machine equipment.

Low-level machine interfaces remain one of the domains where serial protocols rule. Serial communications use simple hardware and have minimal overhead, and something like RS232 has been in real-world use since the 60s. Sure, it's slow, sure it's not great with coping with noise, sure you have to jump through some hoops if you want a connection longer than 15m, but its failures are well understood.

Nothing is so well understood that some developer can't make a mess of it.

Public Function SendCommand(ByVal cmd As String) As String Dim status As Integer ' Write cmd to the serial port using a protocol that is too painful to reproduce here. ' status receives an appropriate value along the way as the protocol checks for various error ' conditions including timeout If status <> 0 Then Throw MakeComPortException(status) End Function Private Function MakeComPortException(ByVal status As Integer) As ComPortException Dim code As Integer Dim message As String = Nothing GetErrorCode(status, code, message) Return New ComPortException(code, message) End Function Private Sub GetErrorCode(ByVal ErrorNum As Integer, ByRef code As Integer, ByRef message As String) code = ErrorNum Select Case ErrorNum Case 129 : message = "Hardware error occured during Send Data" ' Talk Error' Case 130 : message = "System asked to talk but did not recieve Previous Talk Command" ' Nothing to say Case 131 : SendCommand("ERRMS?") Dim EMsg As String = GetResponse() Dim EmsgStart As Integer = EMsg.IndexOf(" (") Try If EMsg.Contains("ERR=") Then code = CInt(EMsg.Substring(4, EmsgStart - 4)) Catch ex As Exception End Try message = EMsg.Substring(EmsgStart) Case 132 : message = "H/W Error while system trying to accept data" 'Listen Error Case 133 : message = "More than 80 characters received before term char" Case 134 : message = "Archive media is full" Case 135 : message = "Listen state interrupted by ESC key" ' Interrupted from keyboard Case 136 : message = "Listen state interrupted by controller sending '*'" ' Interrupted by Controller Case 137 : message = "Error Occured in UART" Case StatusCodes.PortDeviceNotFoundErrorCode : message = "No device Found" Case StatusCodes.PortTimeoutErrorCode : message = "COM port Timeout Error" ' This next occurs if cable is unplugged at controller Case StatusCodes.PortDisconnectedErrorCode : message = "Serial cable disconnected" Case Else : message = "Error #: " & ErrorNum End Select End Sub
 

So, the SendCommand method takes a string and passes it down the serial port. The protocol details were elided here, but we know that we receive a status number. MakeComPortException takes that number and helpfully looks up the message which goes with it, using GetErrorCode.

GetErrorCode is one gigantic switch statement. And let's pay close attention to the message lookup process for error 131. You'll note that we call SendCommand to ask the remote device to tell us what the error message was. But in some cases, it's going to reply to that request with an error code. Error 131, to be exact.

So if we trace this: we call SendCommand which gets a 131 error, which forces it to throw the results of calling MakeComPortException, which calls GetErrorCode, which calls SendCommand, which throws a new MakeComPortException, which…

There's an interesting side effect of this approach. Despite looking like a series of recursive calls, throw unwinds the stack, so this code will never actually trigger a stack overflow. It's actually more of an exception-assisted infinite loop.

For a bonus, note the PortTimeoutErrorCode entry. On the hardware side, they use a custom serial cable which wires a loopback on the RS232 "Ready to Send" and "Clear to Send" pins, which the software uses to detect that the cable is unplugged. It also has the side effect of ensuring that no off-the-shelf RS232 cables will work with the software. This is either a stupid mistake, or a fiendishly clever way to sell heavily marked-up replacement cables.

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


To read the full article, please visit The Daily WTF

Monday, March 18, 2019

Portage and Portability

ST 225 20MB drive and WDC controller

Many moons ago, when PCs came housed within heavy cases of metal and plastic, Matt Q. and his colleague were assigned to evaluate a software package for an upcoming sales venture. Unfortunately, he and the colleague worked in different offices within the same metro area. As this was an age bereft of effective online collaboration tools, Matt had to travel regularly to the other office, carrying his PC with him. Each time, that meant unscrewing and unhooking the customary 473 peripheral cables from the back of the box, schlepping it through the halls and down the stairs, and catching the bus to reach the other office, where he got to do all those things again in reverse order. When poor scheduling forced the pair to work on the weekend, they hauled their work boxes between apartments as well.

As their work proceeded, Matt reached the limits of what his 20 MB hard drive could offer. From his home office, Matt filed a support ticket with IT. The technician assigned to his ticket—Gary—arrived at Matt's cubicle some time later, brandishing a new hard drive and a screwdriver. Gary shooed Matt away for more coffee to better focus on his patient. One minor surgery later, Matt's PC was back up and running with a bigger hard drive.

One day ahead of the project deadline, Matt was nearly done with his share of the work. He just had a few tweaks to make to his reports before copying them to the floppy disks needed by the sales team. Having hooked his PC back up within his cubicle, he switched it on—only to be greeted with a literal bang. The PC was dead and would not start.

After a panicked call to IT, Gary eventually reappeared at his desk with a screwdriver. Upon cracking open the PC case, he immediately cried, "Wait a minute! Have you been carting this PC around?"

Matt frowned. "Er, yes. Is that a problem?"

"I'll say! You weren't supposed to do that!" Gary scolded. "The hard drive's come loose and shorted out the workings!"

Matt darted over to Gary's side so he could see the computer's innards for himself. It didn't take long at all to notice that the new hard drive had been "secured" into place using Scotch tape.

"Hang on! I daresay you weren't supposed to do that!" Matt pointed to the offending tape. "Shall I check with your manager to be on the safe side?"

Gary's face crumpled. "I don't have access to the proper mountings!"

"Then find someone who does!"

Armed with his looming deadline and boss' approval, Matt escalated his support ticket even higher. It didn't take long at all for genuine mounting brackets to replace the tape. He never learned why IT techs were being deprived of necessary hardware; he assumed it was some fool's idea of a brilliant cost-cutting measure. He had to wonder how many desperate improvisations held their IT infrastructure together, and how much longer they would've gone unnoticed if it hadn't been for his PC-toting ways.

[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.


To read the full article, please visit The Daily WTF

Friday, March 15, 2019

Error'd: Do Not Read The Daily WTF

Neil S. wrote, "MSN UK's reverse psychology marketing angle is pretty edgy."

 

"Batman & Lorem was a surprise flop at the box office," writes Art O.

 

Klaus asks, "Do I want to know, why Feedly associates Coffee with restrooms?"

 

"Those idiots, I clearly asked for null_-532419553!" wrote Raymond D.

 

Nigel writes, "I just hope their drugs aren't as genuine as their Windows licenses."

 

"At this point, I don't even remember how long I'd been waiting to get to this point," writes Jake B.

 

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


To read the full article, please visit The Daily WTF