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

Поиск сообщений в 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: The Misleading PIN

Четверг, 29 Сентября 2022 г. 09:30 + в цитатник

Tina needs to write some software that integrates with a hardware device. Thatdevice controls access via behind a PIN, and thus Tina's team needs to track the valid PIN, so that they can, via software, update or alter the PIN.

There's just one problem. That device has some opinions about how a Personal Identification Number should be represented:

/// /// Gets or sets the department PIN. /// /// /// The department PIN. /// uint DepartmentPin { get; set; }

I love the useless comments, but even more I love the datatype: uint.

Now, you might think the PIN 0410 and 410 should be considered different PINs, but you'd be wrong.

This gets us back to the old problem in programming: just because something is called a number doesn't mean it's a numeric type. Whether it's phone numbers, zip codes, or PINs.

Tina doesn't share what this device controls access to, but swears: "It's not our fault. We don't make the device that accepts the PIN."

[Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.

https://thedailywtf.com/articles/the-misleading-pin


Метки:  

CodeSOD: Top Slots

Среда, 28 Сентября 2022 г. 09:30 + в цитатник

Picking random items without repetition is its own special challenge. It's one of those things that's not actually hard, but some programmers have a difficult time coming up with solutions to the problem. Abraham has found these two examples in some code he maintains:

//pick 3 out of 4 int alreadyUsed = 0; while (alreadyUsed < 3) { int rand = random()%4; if(!m_AllOptions[rand]->used) { m_AllOptions[rand]->used = true; alreadyUsed++; } }

Here, they need to choose three items out of a list of four. So the solution is to keep randomly selecting items, and if their used flag isn't true, set it to true and increment. Like a lot of bad solutions to random selection, this one will probably complete in a reasonable amount of time, but might never complete.

//find a free slot int random = std::rand() % 5; while (slots[random].active) { ++random; if (random > SLOTS_MAX) { random = 0; } }

Here, there are a set of slots. I don't know exactly what they're for, but it doesn't really matter. This code attempts to round-robin its way through those slots. It starts by picking a random slot (via magic number, which I assume is equal to SLOTS_MAX, but who knows?). If that slot is active, we keep incrementing our index, wrapping back around to zero. And we just keep incrementing and searching, and we never give up.

You already know how this story ends: a different bug meant that slots weren't getting freed after user, which meant when attempting to grab a new slot, an infinite loop would trigger. Slots were also held onto for multiple seconds, so even after fixing that bug, there was a good chance that this code would enter a busy loop that hung the application while waiting for a slot to free up.

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

https://thedailywtf.com/articles/top-slots


Метки:  

CodeSOD: Containerization

Вторник, 27 Сентября 2022 г. 09:30 + в цитатник

A large company with facilities all over the Asia-Pacific region opted to modernize. They'd just finished a pile of internal development that extended the functionality of a 3rd party package, and they wanted to containerize the whole shebang.

That's where Fred came in, about 9 months into a 12 month effort. Things hadn't gone well, but a lot of the struggles were growing pains. Many of the containers were built as gigantic monoliths. A lot of the settings you might need to do a Kubernetes deployment weren't properly configured. It was a mess, but it wasn't a WTF, just a lot of work.

The efforts of building the containerized, K8s deployments changed the company culture. The new rule was "container all the things", and all the things got containerized. Management was happy to be checking off new buzzwords, and the IT team was happy to have any sort of organization or process around deployments and their environment, since prior to this effort it was a lot of "copy this folder to this server, reboot, and cross your fingers".

Everyone was happy, except for one team, led by Harry. "Your containers broke our software," Harry complained. Now, it wasn't "their" software- it was a purchased product. And like many enterprise software packages, it was licensed. That license was enforced via a smart card and a USB dongle.

Which created a problem. Kubernetes is entirely about running your code absolutely abstracted from the physical hardware it's actually on. The USB dongle requires the code to be running on a specific physical device. The solution to the problem was obvious and simple: don't manage this one product via Kubernetes.

But that wasn't an option. "We use Kubernetes to manage all of our deployments," management said. One of the managers helpfully linked to an interview in a trade magazine where the CTO cheerily shared the benefits of Kubernetes.

"Right, but this particular product is ill-suited to that kind of deployment," Fred and his team countered.

"Okay, yes, but we use Kubernetes for all of our deployments."

And, as of this writing, that's where things sit. Everything must be containerized and hosted in Kubernetes. One software product doesn't play nice in that environment, but it must be wedged into that environment. Currently, the product lives on the same private server it used to live on, but this is a "stopgap" until "a solution is found". Officially it's out of compliance with company standards, and shows up as an evil red light on all the IT dashboards.

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

https://thedailywtf.com/articles/containerization


Метки:  

CodeSOD: A Valid Call

Понедельник, 26 Сентября 2022 г. 09:30 + в цитатник

"Never trust your inputs" is a generally good piece of advice for software development. We can, however, get carried away.

Janice inherited a system which, among many other things, stores phone numbers. Like most such systems, the database validates phone numbers, and guarantees that numbers are stored in a canonical format, as text.

For some reason, their Rails presentation layer isn't satisfied with this, and needs to validate the data coming from the database. In their specific environment, they know the database only contains canonical phone numbers, but honestly, I'm willing to forgive the belts-and-braces approach, as I've certainly used enough databases that couldn't provide those kinds of guarantees.

No, the problem is the way they went about it.

phone = acct.phone_number.to_s raise "phone number blank!" if phone.blank? phone.gsub!(/\+/,'') if (phone =~ /\A\+[0-9]+\Z/) phone = 'phn:'+phone elsif (phone =~ /\A[0-9]+\Z/) phone = 'phn:+'+phone else raise "phone number: incorrect format!" end

So, first, we convert the text field in the database to a string, which of course it already was. Then we use gsub to strip any "+" characters from the string. Then, we have our if statement, where we check two regexes.

First, we check if the string is a + followed by 1 or more digits. This branch will never be true, as we just removed all the plus signs. Then we check if it's a series of digits. If it is just a series of digits, note that we put the + back on, right after removing it. This does guarantee that there are no middle +, which isn't a thing the database would allow anyway.

But this doesn't guarantee a valid phone number. It just guarantees that we only display phone numbers which contain at least one digit and any number of + signs. The number of digits isn't accounted for (which will have international variations but we can sorta set a range of how many characters there should be).

The fact that this phone number validation is wrong ends up not mattering, though, as the data in the database is valid.

I don't even know what the phn: is intended to be- it looks like it might be intended as a URL protocol, but the phone call protocol is tel:. It might be a formatting convention, but I have some doubts that string concatenation is the right way to do it.

[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-valid-call


Метки:  

Error'd: Ixnay

Пятница, 23 Сентября 2022 г. 09:30 + в цитатник

I know that I recently implied a fondness for cooked corvid, but if this keeps up I'm going to turn vegan. It will be a sad day if I have to turn in the barnyard puns.

Reader Ruthless R. goes in HAM, crowing "Daily WTF goes WTF with its RSS Feed." It's getting to be less funny.

oops

 

Regular gargler Argle Bargle rooted up this error, roasting phlegmatically "A lot of people using MSN's comment sections have been complaining about crazy levels of censorship. Sometimes vicious insults are let through uncontested, sometimes the posts are marked held for review, sometimes you are told that the most innocent of comments are not acceptable to community guidelines, but perhaps the weirdest form of censorship is an error reading Something went wrong. Please try again. Trying again never works. Sometimes rewording and trying again never works. On a whim, I tried submitting something about pig Latin." That didn't work either. Ookslay ikelay eirthay fanityproay ilterfay okedechay.

ixnay

 

Never Wimpy Evan R. is planning to murder some hamburgers, grunting "Let me just crack open the debugger to order some sliders."

apple

 

Adam R. is headed to market, jiggety jig. "I wanted to know if my bank provided any foreign currency services and came across this FAQ entry on its website. Their answer was not helpful." But technically correct.

yes

 

Allie C. bastes Google, dripping "Javascript injection + regex really is less good news!"

jsinj

 

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

https://thedailywtf.com/articles/ixnay


Метки:  

Model Years

Четверг, 22 Сентября 2022 г. 09:30 + в цитатник

Caleb (previously) continues to work for a vehicle finance company. Most recnetly, he was working on a data ingestion application. Its job was to pull in a big ol' pile of CSVs from a mix of vendors and customers and feed it into a central database to keep things up to date.

"Application", however, is misleading. In reality, it was a suite of Access databases scattered around various network shares. Each represented a custom data loading pathway for a kind of data. It wasn't true that each was isolated from every other- frequently, the data flow would be "Open database \\fileserver\processing\vendor01.mdb, use the form to load the CSV file, then open \\fileserver\processing\process01.mdb, but only AFTER you've deleted the CSV file."

Caleb's job was "easy": trawl through this thicket and figure out which parts handled just vehicle model information, sourced from vehicle manufacturers. Figure out what it did, and then reimplement in something that wasn't a fragile pile of Access databases.

While working on that, a new problem appeared: manufacturers were announcing their 2023 model numbers, but the system simply couldn't ingest those. No vehicles with 2023 model numbers could be created. After searching for awhile, Caleb figured out that it went through this table, created in 2008, which hadn't had any data added/removed since:

ModelYearAbbr ModelYear
4 2004
5 2005
6 2006
7 2007
8 2008
9 2009
10 2010
11 2011
12 2012
13 2013
14 2014
15 2015
16 2016
17 2017
18 2018
19 2019
20 2020
21 2021

Now, this isn't particularly shocking, and honestly, probably wasn't even a terrible idea. It's just that, since new years were never added, it made it impossible to add vehicles in the 2023 model year.

But that still left Caleb with another question: their system had vehicles with a 2022 model year just fine. Did a bug let the data load last time? Is there another code pathway Caleb hasn't found? Is there a mystery Access database on a file share no one remembers that can handle model years more recent than 2021? No one knows, and truly, does anyone want to know? Down that path lies an eldritch madness, a cosmic horror that would cause our very souls to bleed.

(Or, probably, someone just manually inputted all that data, but the eldritch thing is more fun.)

[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/model-years


Метки:  

CodeSOD: The Base Model

Среда, 21 Сентября 2022 г. 09:30 + в цитатник

Penny uses a Python ORM. Like most ORMs, it involves a lot of "inherit from a BaseModel class, and get all your database access stuff for "free". Or at least, it used to. They've released an update.

def __init__(self, *args, **kwargs): if hasattr(self, "ACCESS_POLICY_VIEWSET_NAME"): deprecation_logger.warn( f"The model {self.__class__} defines the 'ACCESS_POLICY_VIEWSET_NAME' class " f"attribute which is no longer required and is discouraged to be set." ) return super().__init__(*args, **kwargs)

Now, this is an interesting class of breaking change. Everyone like Penny has been class MyEntity(BaseModel) for the entire time they've been using the framework. Whether or not that's a good way to do ORMs, it's going to disrupt a lot of people's code.

In Penny's case, their application uses the ORM for syncing data between large databases, and they're large and complicated- thousands of entities have to get synced, and each entity inherits from that BaseModel class. This means that not only does nearly every entity need to be changed, but also that every time they run their code, they generate many many thousands of lines of logged warnings.

[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-base-model


Метки:  

Editor's Soapbox: TODO: Post an Article

Вторник, 20 Сентября 2022 г. 09:30 + в цитатник

Yesterday, I briefly mentioned the "TODO" comment as part of the WTF. Anyone who develops software for long enough is going to develop some pet peeves. Lord knows, my feelings on Hungarian Notation are well established. Or ternaries, though honestly, for ternaries, I mostly am in it for the puns.

But, I've got another pet peeve that's crawling up my butt far enough that I felt the need to do a soapbox about it.

//TODO: explain why I hate //TODO

Yes, I'm about to suggest that TODO comments should go away, or at the very least, need to be used well, which they frequently (always?) are not. There's nothing inherently wrong about leaving a TODO in code, but there are a lot of things that can go wrong with them. Enough things that go wrong that I'll just come right out and say that TODOs are a code smell.

Let's start with a "good" TODO comment, for an example.

//TODO: These weights are a first approximation. // Tune them according to real-world testing data, see (link-to-some-document-here)

A good TODO comment has to have three key things. First, it has to capture the state of the code as it is. Second, it needs to describe why it's not ideal. Third, it also describes what must be done, in an actionable way. Note, in this example, it includes a link to an external resource to find more information.

Those are the three traits about the comment itself that must be true for it to be good, but there's also a situational truth that makes a good TODO comment: it must be time consuming enough to do that you didn't do it right away, and it must be low-priority enough that you don't need any accountability for making sure it gets done.

What you see above is a best case scenario. Here are a few more realistic TODO comments culled from some projects I have seen in various places, some open source, some not, all struggling with code quality.

This first one is not so bad, honestly:

// TODO: this method WOULD work if the underlying library could handle unlimited results. This might be throwing out results? Can this be fixed?

My big complaint here is that this is a complicated task with no real clear solution- we shouldn't be tracking things like this in code. We need a task which can be assigned to someone, in some sort of task tracking tool. Yes, every single task tracking tool is garbage, and as someone who has recently started using Jira, some tracking tools are more garbage than others. But the ability to track who is working on what is important.

// dump_log(data, fname, size); // TODO: Remove

This is one of my favorite kinds of TODOs: a reminder to remove a line that's already commented out. It's almost like maybe we should have removed the line instead of commenting it out. There are folks for whom source control remains a dark art, and "commented out code that isn't dead" remains one of the main ways that manifests, and weirdly, seems to happen alongside TODOs quite a bit.

Then there's the whole class of TODOs: the appeals to ignorance

// TODO: what should be here? // TODO: verify that this is the right way to do this? // TODO: handle this thing correctly // TODO: what does status mean here? // TODO: @JoebobBobsen what is this i don't even

And of course, the apotheosis of appeals to ignorance:

// TODO: ??

At the end of the day, tracking tasks via comments in code is bad. You can't see who is working on what, you can't easily prioritize your work, and it's inconvenient to attach discussions and documentation to comments. Maybe there's a great IDE plugin out there, that lets you treat TODOs like tasks, but at the end of the day find a task tracking tool your team likes and use it. Please. Otherwise, you'll inevitably find more comments like:

//TODO: this isn't working right now. Fix it.
[Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!

https://thedailywtf.com/articles/todo-post-an-article


Метки:  

CodeSOD: Bitmaps and Streams

Понедельник, 19 Сентября 2022 г. 09:30 + в цитатник

Robert has inherited a .NET application. It's a big-ball-of-mud, full of monstrous classes of thousands of lines and no coherent purpose, complete with twenty constructors.

It's ugly and messy, but it's mostly just generically bad. This method, however, is a lot of bad choices in very few lines.

/// /// TODO implement !!! /// /// The file. /// public static Bitmap WriteFileFromByte(byte[] file) { Bitmap retVal = null; using (MemoryStream ms = new MemoryStream(file)) { retVal = new Bitmap(ms); } return retVal; }

We start with a TODO, one of my "favorite" comments. The method is called WriteFileFromByte, but that's exactly what doesn't happen.

Instead, this converts a byte array into a MemoryStream, and then creates a Bitmap off of that stream. That's actually all fine. We need to convert the byte array into a stream so that the Bitmap class can ingest it.

So, what this method does is simply convert a byte array into an image object. You wouldn't know that from the name, you wouldn't know that from the comments. The one thing that hints at a deeper WTF is that the byte[] is called file, which implies that we loaded this data from a file- when we could have just used a stream in the first place.

Oh, there's one more WTF. This method has been in the code base for a long time- but it's actually never been invoked anywhere. It's a dead method with a bad name and there are a bunch of other, similarly bad and confusing methods, which do the same task but in different (and frequently harder to use) ways.

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

https://thedailywtf.com/articles/bitmaps-and-streams


Метки:  

Error'd: Taking the Piss

Пятница, 16 Сентября 2022 г. 09:30 + в цитатник

In case anyone is wondering "is there anything so lame that it's not even good enough to get published by Error'd", the answer is yes. There is a category of submissions that is very common, but in the completely capricious opinion of this editor, just not very funny. That category is clearly broken listings on amazon.com. We usually get two or three of these every week. We save them up, and maybe someday the news will be so slow that we have no choice but to run an entire column of nothing but Amazon bloopers. This week was no different from the usual, except that this time the September stress has struck a nerve and so you get to see what the brink of madness looks like from the inside.

Tippler Matthias poured one out for us. "Seems someone already tried some of the good stuff while uploading the images to Amazons catalog."

dewars

 

Toddler Rob H. tee-hee'd "From ServiceNow's attempt to truncate the Description field (customer e-mail body) to a small space... the wish, of course, was for a nice weekend. Who knew it would lead to a bit of Monday morning toilet humor?"

wee

 

Number-crosser Drew W. has a first with this. "I don't know how, but either Apple Numbers or Microsoft Excel has made font typos into a thing. (It's Calibri, not Calirbi)"

calibri

 

Cinephile Mike T. ad-libbed dramatically "I was just trying to browse a local theatre's website when this error message barfed up on my screen, apparently due to Facebook ... something."

faace

 

Quoth Apple-sauced Carl C. in confusion "I can only surmise that this product works so well that it blocked its own ad?"

mac

 

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

https://thedailywtf.com/articles/taking-the-piss


Метки:  

Version Numbers

Четверг, 15 Сентября 2022 г. 09:30 + в цитатник

Initech was the big customer for Chops's company. And like a lot of big customers, they had requests and they had the weight to throw around to get their requests fulfilled. When they wanted a new feature, they got a new feature. When they found a bug, they got the patch ASAP.

No matter how special Initech thought they were, they were mostly requesting things that other customers wanted anyway, so it worked pretty well.

So, one day, they submitted a pile of feature requests, the dev team got to work, and cranked out the features. They tested it, they shipped betas out to the customer, the customer liked the changes, confirmed that it passed user-acceptance, and was ready to deploy. Well, almost ready. There was one tiny little problem.

"So, we can't do this upgrade," said Jerry, the lead from Initech. "It violates our IT policy."

"Um, how?" Chops asked.

"Well, the current approved version in our environment is 3.4.24. The version you're shipping us is 3.5.1. That's too big a version number change."

"Oh, uh… we shipped 3.5 a few months ago…"

"Right, but we haven't gotten that approved. Can you add these features to the 3.4 version?"

That request got escalated up to management, and since Initech was a big customer, management said, "Yes, absolutely, do it."

The result was a disaster. While 3.5 and 3.4 were basically the same from the end user's perspective, a lot of internals had changed. The new features used the new internals, and when trying to backport them it was a lot of work. They started from the codebase of 3.4.30 (the last release of 3.4.x), and ended up breaking everything. Tests which passed under 3.5 started failing, tests which had been passing under 3.4 also started failing. No one was exactly sure how to backport these features to the old internals and it was eating a lot of developer cycles.

Chops watched this slow motion disaster, and watched management getting increasingly upset. Initech wanted their new features, and they wanted them last week. So Chops decided to take matters into their own hands. They took the 3.5.1 build, and re-set the version numbers to be 3.4.31.

"Hey, Jerry," Chops said. "I've taken the latest version, 3.5.1, and I've renamed it 3.4.31. So the official version number is 3.4.31. Is that okay?"

"Uh, the version you're giving me is 3.4?"

"That's the version number on the file, yes. But the code is actually 3.5."

"But the file says 3.4?"

"It does," Chops said. "And the 'about' information will also say 3.4.31."

"Perfect, that'll do."

Chops sent the file over. Jerry ran it through all their tests and confirmed it was still satisfactory. Initech's management confirmed that the version number only incremented a small amount, and it was still "officially" a 3.4 version.

Everyone was happy with this outcome.

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

https://thedailywtf.com/articles/version-numbers


Метки:  

CodeSOD: Walking is your Duty

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

Embedded chip documentation is sometimes very bad, and very confusing. Frequently it's difficult to really understand the ins and outs of a given chip without simply getting experience.

Which is why Mr. Scrith was a bit surprised with this code, which came from someone who definitely should have known better.

This code is for a "walking 1s" memory test- it simply visits every address in memory and writes a "1" and confirms that it can read back that "1". Such a test poses an interesting challenge: you can't use any variables, because they will live in RAM somewhere, so you need to limit yourself only to the registers exposed by your CPU.

And that's where this developer made their odd choice. This particular CPU had plenty of general purpose registers, and a bunch of special purpose registers, like a set of registers for controlling PWM generators. The developer either couldn't find the correct way to access the general purpose registers or didn't care to try, but either way, the end result was that they used the PWM registers for everything:

PWMDTY01 = RAM_BASE; // address PWMDTY23 = START_VALUE; // value PWMDTY4 = 30; // counter PWMDTY5 = 0; // retries for ( PWMDTY5 = 0; PWMDTY5 < 2; PWMDTY5 ++ ) { for (PWMDTY01 = RAM_BASE; PWMDTY01 < RAM_END; PWMDTY01 += sizeof(uint16_t) ) { *((uint16_t*)PWMDTY01) = PWMDTY23; PWMDTY23 <<= 1; if ( PWMDTY23 == 0 ) { PWMDTY23 = START_VALUE; } } for ( PWMDTY4 = 0; PWMDTY4 < 16; PWMDTY4 ++ ) { PWMDTY23 = _PowOfTwo_16[PWMDTY4]; for (PWMDTY01 = RAM_BASE; PWMDTY01 < RAM_END; PWMDTY01 += sizeof(uint16_t) ) { if ( *((uint16_t*)PWMDTY01) != PWMDTY23 ) { PWMDTY4 = 30; PWMDTY01 = RAM_END; } PWMDTY23 <<= 1; if ( PWMDTY23 == 0 ) PWMDTY23 = START_VALUE; *((uint16_t*)PWMDTY01) = PWMDTY23; } } if ( PWMDTY4 <= 16 ) { for (PWMDTY01 = RAM_BASE; PWMDTY01 < RAM_END; PWMDTY01 += sizeof(uint16_t) ) { *((uint16_t*)PWMDTY01) = 0; PWMDTY5 = 2; } } } if ( PWMDTY4 > 16 ) { ramTestPassed = FALSE; } else { ramTestPassed = TRUE; }

The code works, but it's certainly an odd choice. When Mr. Scrith suggested that PWMDTY23 wasn't the clearest choice of register, the developer said, "Oh, should I #define a macro no name it more clearly?"

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

https://thedailywtf.com/articles/walking-is-your-duty


Метки:  

CodeSOD: Up the Garden Path

Вторник, 13 Сентября 2022 г. 09:30 + в цитатник

Sam worked on an application which needed to parse files out of a directory. There was a ticket to change the search path for those files to search an additional directory. That didn't turn out to be terribly hard, but the existing code raised some serious eyebrows.

def get_info_for_identifier(base_name: str, identifier: str) -> dict: ... all_ids = os.listdir(base_name) ... results = {} for i in all_ids: results.update(parse_identifier(base_name, i)) ... return results[identifier]

This is the first method we're going to look at. You can see that it starts by listing a directory, finding every file in it. Then, we iterate across all of those files, parsing them and adding them to a dictionary. We then return… just one key in that dictionary. The one for the one file we actually cared about when we called this method. So it parses every file, to return the results for one file.

And this is the first method we're looking at, because that's just the framing device for our WTF. Note how it calls that parse_identifier method. Let's take a look at that one.

def parse_identifier(base_path: str, identifier: str) -> dict: main_file = Path(os.path.join(Path(base_path), identifier + ".details")) ... files = list(base_path.glob(main_file.name)) if len(files) > 1: raise InternalError("this shouldn't happen") return parse_files(files)

So, Python has two ways of managing filesystem paths. The "old" way, and the outdated way, is to use the os.path library, and methods like join. I wouldn't say it's wrong to use os.path, but it's definitely better to use the newer Pathlib, which has the Path object in it. You know, the Path object that you see them using in this method.

That first line should be: main_file = Path(base_path) / (identifier + ".details". Or os.path.join(base_path, identifier + ".details"). This mixing and matching is definitely wrong.

But, the end result of this operation is that we have a path to a single file. So then we use the Path.glob method of base_path which… is a string. So it doesn't have that, except in Python type annotations aren't enforced at runtime, so this code's type annotations lie and it wouldn't pass a type-checker.

But we glob for main_file.name, but main_file is also a Path object, so we don't need to do any of this, and also why are we globbing when we know we're only pointing at one file at most (or maybe no files, if the file doesn't exist).

And then, and then, we do a check- if we found more than one file, we throw an exception: "This shouldn't happen".

And that's true. This absolutely shouldn't happen. None of this should happen. None of this should have happened.

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

https://thedailywtf.com/articles/up-the-garden-path


Метки:  

CodeSOD: Undefined Variable

Понедельник, 12 Сентября 2022 г. 09:30 + в цитатник

Robert H was trawling through the JavaScript front-end for his team's ASP.NET MVC application. The goal was to prepare for a complete rewrite of the front-end, because, well, it had problems and wasn't reliable or maintainable.

As an example, Robert sends this:

function orderSearch() { // ReSharper disable once ConditionIsAlwaysConst if (typeof loadingText === "undefined") { var loadingText = window.Resources.Messages.Loading; } … }

This code is a wonderful example of (ab)using the var keyword, instead of the newer let keyword for defining variables. var declared variables automatically get "hoisted"- they're always scoped to the function.

Which highlights why this code is pointless: of course loadingText is undefined, we literally define it on the next line. Given the way the variable is used, this entire block could be redefined as:

const loadingText = window.Resources.Messages.Loading;

But the real gem in this code is the ReSharper hint. Their linting tool complained about this pointless conditional, throwing up a warning that the ConditionIsAlwaysConst: it can't be anything but true. But even with the tool pointing them in the right direction, they couldn't think through why that was the case, so they just turned off the warning.

While this isn't a serious bug in the code, this does put in mind the person who is annoyed that their Carbon Monoxide detector won't stop going off, so they unplug it. It's easy to pass linting if you disable any warning that comes up.

[Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.

https://thedailywtf.com/articles/undefined-variable


Метки:  

Error'd: Crowneisseurship

Пятница, 09 Сентября 2022 г. 09:30 + в цитатник

Never let it be said that we at TDWTF don't enjoy the taste of our own medicine. Andrew I. shares with us a little taste of his own crow, and then we share with you a little taste of Remy's. It's not quite a full meal, but you can call it an amuse bouche.

But first, Sam B. serves up some sure fled pie. "This Brexit business is getting out of hand. Lenovo says even the United Kingdom has left the UK."

brexit

 

And Kevin G. found Newsweek has birthed a novelty: "It's a brand-new Date in August!"

august

 

Super Saver Michael B. seems to be doing it wrong, but it's not his fault. "If only I could renew without the discount..." he rues.

discount

 

Proud Andrew I. poses "My next question is: will November 24th be listed as President's Day, or are they stuck on New Year's Day?"

holiday

 

And shortly thereafter a humble Andrew I. wrote us back, regretting "My snarky comment SHOULD HAVE BEEN: My next question is whether November 24th will show as MLK Day, or if it will be New Year's Day again. Seriously. I had an off-by-one-holiday bug." It's OK, Andrew, it happens to the best of us.

Finally, as promised, keen Klaus cruelly crowed "Just an example of your markdown parser taking a stab at a typo :)" But our feelings aren't hurt, are they, Remy? Remy?

remy

 

[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/crowneisseurship


Метки:  

CodeSOD: Oh, Poop

Четверг, 08 Сентября 2022 г. 09:30 + в цитатник

Pearl was paying down some technical debt. She was trawling through their NodeJS application with a search for TODO and console.log. She was triaging the TODOs, and replacing the logs with a real logging framework.

The application was old, had many complicated routes for requests to be handled, and buried deep in a file was this code, which was clearly testing code that was never meant to end up in production:

var express = require("express"); var router = express.Router(); /* GET home page. */ router.post(poopRoute, function (req, res, next) { const { poop, despacito } = req.body; console.log(poop); console.log(despacito); const ok = "ok"; return res.json({ ok, poop, despacito }); }); module.exports = router;

Poop indeed. It was obviously easy for Pearl to just remove this code, its potty humor, and it's completely not dated pop-culture reference from 2017. But the funniest part of this code, for me, is that the comment tells us that it's a GET request, when the code tells us it's a POST request. The mismatch is so sad. Alexa, play Despacito.

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

https://thedailywtf.com/articles/oh-poop


Метки:  

CodeSOD: Enumerating Your Plants

Среда, 07 Сентября 2022 г. 09:30 + в цитатник

Usually, we don't pick on game code, as it's frequently bad because of the time constraints under which it's developed and because the concerns are more around "making a fun, performant game," and not "writing good reusable code".

But there are some egregious exceptions, like what happened to Patrick. He was handed some C# game code, and told, "Good luck!"

This particular block lived in a file called banana.cs. Does this game have anything to do with bananas? It does not! It has to do with zombies. No, it is not Plants vs. Zombies, though given the botanical flair in this code, perhaps the author was a fan?

One module of the game uses integers as the ID values of enemies. One module uses strings. No one uses enums. So when you want to convert the IDs to the appropriate type, you need to call enemyIdNumToName, which I want to stress- is not the display name of the enemy.

public static string enemyIdNumToName(int inId) { string returnData = ""; switch(inId) { case 0: returnData = "Radish"; break; case 1: returnData = "Tomato"; break; case 2: returnData = "Orange"; break; case 3: returnData = "Banana"; break; case 4: returnData = "Strawberry"; break; case 5: returnData = "Carrot"; break; case 6: returnData = "Watermelon"; break; case 7: returnData = "Grapes"; break; case 8: returnData = "Broccoli"; break; case 9: returnData = "Bell Pepper"; break; case 10: returnData = "Coconut"; break; case 11: returnData = "OneGrape"; break; } return returnData; }

This code takes an integer, and converts it into a string. The integer has no inherent meaning. The string has no inherent meaning. This function does no validation to confirm that the integer is in the correct range, and if it's not, the switch doesn't sanitize or protect it at all. Invalid inputs don't get trapped or even logged. And no, the downstream code doesn't play nice if you pass it an empty string.

Which, finding this block did help Patrick diagnose a crash (an integer that was out of range was getting passed in), so at least it served some purpose.

[Advertisement] ProGet’s got you covered with security and access controls on your NuGet feeds. Learn more.

https://thedailywtf.com/articles/enumerating-your-plants


Метки:  

Not-so-Simple Network Management Protocol

Вторник, 06 Сентября 2022 г. 09:30 + в цитатник

"Phillip, are you familiar with SNMP? Do you know Python?" asked Phillip's new boss.

"No."

"Would you like to be?"

That's how Phillip got thrown into the deep end of a conversion project that was tasked with updating their infrastructure monitoring system. It was developed by a team a few years ago, and they all quit at the same time, which made it hard to maintain.It was a homegrown set of Python scripts which polled a Prometheus service, which itself was gathering metrics from a pile of Docker containers. These scripts gathered those events and turned them into SNMP alerts for a third party receiver.

The upgrade promised to be simple: take the SNMPv2c code and update it to use SNMPv3, which supports encryption. Phillip started by pulling the existing code from their repository, only to find that while there was a repository and it had a pile of branches, nothing had ever been merged into main/master/trunk. So Phillip pinged one of the other developers: "Which is the correct version of the code?"

He started playing with the PySNMP library while he waited. From reading the docs, Phillip thought that it should be a very simple change- essentially a find/replace to update one class name. After a few days of poking at the library, the previous developer gave him about three candidate branches which were probably what was actually deployed. Phillip found a Docker image that seemed to have the same code as one of those branches, and was probably the one deployed- no one knew for certain- and set to work.

His first attempt didn't work at all, which wasn't surprising. There was no logging, the configuration was hard-coded in half a dozen places in the code and didn't always agree with the other places, and someplace along the way it needed an SNMP command, which nothing was sending. It was mess, but eventually, Phillip got it running.

For a few minutes, anyway. Then it would crash. It took Phillip two months of research and experimentation to discover that the SnmpEngine object wasn't threadsafe. It wasn't his choice to use it across multiple threads- that was the architecture that the previous developers had used.

That's when it dawned on Phillip: this program had never worked. Sure enough, the deployed version crashed all the time, too. So Phillip set about refactoring and debugging it, and after two more months, he had a thing that could read the metrics and report them to SNMP.

Except the third-party receiver that expected to receive those messages didn't get them. Phillip could confirm he was sending it, but it wasn't arriving. Cue another month of scrambling and head-scratching, only for Phillip to discover that the network team had blocked the routes from the server he was running on and the third-party receiver.

"Oh, it was sending so much traffic, we assumed it was broken," was the best explanation he could get.

So the service never worked in the first place. Even if it had worked, the network team had blocked it from working. No one talked to anyone else about what was going on. And, as the cherry on top of the sundae, the main customer for this data didn't believe in "on-call rotations"- they got ahold of the developers' cellphone numbers and called them directly whenever they had an issue.

All that added up to Phillip leaving the company after a very long six months. It also neatly explained why the previous dev team had all quit en masse.

"Still," Phillip writes, "at least I got some Python experience out of it."

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

https://thedailywtf.com/articles/not-so-simple-network-management-protocol


Метки:  

Classic WTF: Security By Oblivity

Понедельник, 05 Сентября 2022 г. 09:30 + в цитатник
It's a holiday in the US, so once again, it's time to reach back into the archives. Two-Factor Authentication is pretty standard these days, but once upon a time, it felt far more cumbersome to use. This story from 2006 highlights some… unique solutions to the problem. Original --Remy

Laptops are blessing for many corporate workers: never before has it been so easy to bring work home and neglect one's family to get in a few extra hours of unpaid overtime. As eager as employees are to do this, the mean ole' folks in IT Security are not. They cite all these news stories about sensitive data being lost as a result of laptops and remote access, and say it's just not safe to bring the company work home.

Thankfully, the IT Security director at MK's company (a fairly large banking institution) knows that the ability to conveniently work remotely is much more important than working securely. Shortly after some mean ole' regulatory agency mandated that remote access is secured with a VPN that requires typing in a constantly changing passcode from a physical token, the director had just the solution for everyone ...

Hey All,

I know there have been a lot of complaints about the new RSA tokens that we've issued, in that it's a bit of an inconvenience to carry your laptop AND an RSA token on your key ring. Here's a solution that will help you keep them together.

Get a bigger key ring (we've got a handful, first come first serve) and put the token on  the key ring using the small diameter ring on the token. Insert the laptop's power cord through ring, make a half hitch loop on the cord, fastening the bigger ring to the cord. Here's a (blurry) picture to give you an idea:


 
Regards,
Thomas J-----
IT Security

It was the perfect addition to the name and passwords that manylaptop users had taped to the top of their screen. And just as secure.

[Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.

https://thedailywtf.com/articles/classic-wtf-security-by-oblivity


Метки:  

Error'd: Pub Kick

Пятница, 02 Сентября 2022 г. 09:30 + в цитатник

Last week's article nearly exposed to the public the lowest-key techreligious war that has been waging for decades. PEBKAC versus PEBCAK completely underwhelms the emacs vs vi war, the GUI vs CUI massacre, the tabs vs spaces schism, and even the -- + // alliance against the /* and (* comment markers. Scratch a PEBCAK partisan and all you'll find is a bit of blood and a response of "OW! Why did you do that?! There isn't any war!!" Even the partisans deny it exists but it simmers. It's PEBKAC, I tell you. PEBKAC! Wait, I forgot. Which did I use in last week's article?

Plotzed publican Peter G. has tired of his local and decided he'd rather pop round to das Lokal for a schnitzel. Researching reviews, he was surprised by an unexpected mountain PICNIC (Problem In Chair Not In Computer). "Dumont Travel seem to think the Anschluss is still in effect, or at least this is what you get when you ask for travel info for Austria ("Osterreich)."

dumont

 

No slouch he, sot Johannes tipples like a man: at home, alone. Low on supply, he went online for a bev. "I know, Austrians (No kangaroos here) do like beer. But the comparative price is normally calculated to 1 Liter or 1 KG. Surely not 500 Liter (132.08603 Gallons)." Bloody oath, mate! That's a lifetime supply of Egger M"arzen!

bier

 

Sober and studious Rob broke out a new pen to compose a longhand letter, but quickly caved to the convenience of our online submission form. Not so much an EBKAC as a WiTCh (Trouble 'twixt Wig and Chin), Rob elaborates. "School is about to start, and the school has made the Student and Parent handbook available, with a qr code on the school website. If only someone clever could invent an easier way for a website to refer to some other content on that website. Note also the helpful mouse-over text."

scanme

 

For our penultimate posting, peckish backer Rich Di C. pondered "I am sure there's a test case reading Ensure text appears on side of carton. CHECK!" I'm starving for a juicy acronym to name this.

burger

 

Finally, flat Emmet H. cheeped out "One would like to think that the developers of online banking portals are above average, and held to a higher standard than your average web dev. One would be wrong." That's still enough dosh for one each of Johanne's coldies, E. Prost!

moral

 

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

https://thedailywtf.com/articles/pub-kick


Метки:  

Поиск сообщений в rss_thedaily_wtf
Страницы: 124 ... 122 121 [120] 119 118 ..
.. 1 Календарь