Hacker News new | past | comments | ask | show | jobs | submit login
A bug I wish I hadn't caught (roganmurley.com)
241 points by fagnerbrack on Aug 15, 2019 | hide | past | favorite | 94 comments



See also: A bug so cool that the development team was reluctant to fix it (https://devblogs.microsoft.com/oldnewthing/20190603-00/?p=10...)


Reminds me of the old Dota2 Fountain hook glitch. A Valve employee commented that they deemed it "Too hilarious to fix"[1]

They eventually patched it after a pro player abused it to turn a game around at the International 3[2]

It's a shame because 6 years later it's still one of the best moments I ever witnessed in the game.

[1]: https://dev.dota2.com/showthread.php?t=2989&p=11512&viewfull...

[2]https://www.youtube.com/watch?v=oB0tUrfDz6A


I was really quite disappointed about fountain hooks being removed - they were an extremely high skill, high risk high reward maneuver. It was also ridiculously fun to watch NaVi pull it off game after game in TI3 - part of what made that my favorite year for the spectator aspect of the tournament.


I honestly thought fountain hooks were a legitimate part of the game, until they were removed. They're hard to pull off. You could also sabotage your team by teleporting members with Wisp/Io to the enemy fountain. Ahh, the worst of times.


See also: 'FadeAway' grabs in League Of Legends. Very similar concept, amusing to ponder the ways in which the programmers made the same oversight: https://www.youtube.com/watch?v=WQp63SA-NZY (12s in)

Essentially, moving the target of the 'pull' while the pull is ongoing. Pudge->Fountain for DoTA, Blitz->Thresh for LoL.


Obligatory xkcd? https://xkcd.com/1172/


The first sentence has its own bug. "there was a big filed against Outlook"


I wonder why they didn't just decide to have a more finite "history" so that they could keep the "parlor trick."


The parlor trick isn't a useful feature in practice. If a user drags a Note around a bunch, drops it, and then selects undo, what they really want is to undo all the way back to its location at the beginning of the drag. They don't want to rewind the entire drag procedure one pixel at a time.

I've dealt with this issue in various tools and level editors a few times. It can be annoying. The fundamental problem is that if your tool has undo (which it should), the cleanest way to architect it is such that every state change goes through undoable operations.

But that means that even in the "middle" of an operation like dragging something, or painting a long meandering line, you need to be creating and processing individual undoable steps so that the user can see the operation as it proceeds.

But once the operation completes, if they undo, they (usually) want to undo the whole batch of them, not each tiny step. A closer-to-home example of this for most programmers is their text editor. Type a sentence quickly and then hit undo. You don't want that to just undo literally the last character.

There are two ways I know to handle this:

1. If memory is less of a concern, I keep the series of individual undoable steps and then wrap them up in a single "multi-step" undoable operation. Then, in the main undo queue, replace them with that wrapper so that they are all processed as a single operation. When you undo the wrapper, it just undoes all of its child steps in reverse order.

2. If memory is more of a concern, I add support for collapsing a series of undoable operations into a new larger one that can represent the entire aggregate change more efficiently. This is more work because you need to write separate code for each kind of operation that can be batched this way.


> Type a sentence quickly and then hit undo. You don't want that to just undo literally the last character.

I am continually irritated by this behavior.

Yes, I do want to undo one operation. If I need to go fast and have little regard for correctness I can hold the button down.

Don't make me play the game where I hit undo, it undoes the whole sentence (or several), so I hit redo to bring it all back, and then I have to click backspace 5 times to get to where I wanted. Worse when I'm using multiple cursors and doing operations of different lengths to each line.


Sounds like you need Vim in your life.

To keep things short: Whenever you want to insert some text you need to switch to Insert mode. When you're done you Esc out back to Normal mode. Undo will undo everything you did inside the last Insert.


> Sounds like you need Vim in your life.

> To keep things short: Whenever you want to insert some text you need to switch to Insert mode. When you're done you Esc out back to Normal mode. Undo will undo everything you did inside the last Insert.

That's a more extreme version of the behavior I'm objecting to. Why would I prefer that?


I'm having trouble understanding what you want.

Undo is for undoing an action, like inserting a bunch of text.

If you want to delete one character at a time backwards... use the backspace key?


Honestly the issue is mostly due to wanting a slightly smaller, but not one character, undo. I think the problem is just that the things that I view as pauses and separate actions are almost always shorter than what the undo function sees, and undo undoes enough that it's quicker to redo and backspace than retype.


> That's a more extreme version of the behavior I'm objecting to. Why would I prefer that?

Put something in the wrong place (probably via pasting, but it's not always clear to a screen editor if you pasted or just typed quickly)


Typically when I paste something, I type something beforehand, and then paste it in, undo it, and it undoes what I typed before.

This is worse when I'm using multiple cursors, which is usually me manually cleaning up some data.


Still use vim. You can use something like "5db" to delete the previous 5 words. For more precision, "5X" will delete your last five characters. And if you have a very specific use case, macros are a big help. If you have a very specific and recurring use case, you can script in vim script, ruby, perl, python (2 & 3), tcl, racket, and lua. There may well be support for others of which I am not aware.


Undo is an transactional operation... backspace five times is precisely what backspace is for and would make undo less powerful if it undid every single keystroke.


My problem is that my mental model for what is an undoable transaction is almost always smaller than the editor's, to the point where I try to undo, get surprised by how much was lost, and then redo and control+backspace until I've deleted what I need.


The sane way to do that is to split the UI and edit, so that changes in the UI (like pixels while dragging) don't enter the history. I worked on one application that did this, and the results were almost ideal.


1a. As a bonus, offer coarse undo and granular undo (where granular undo always undoes an atomic operation, and coarse undo undoes the “multi-step” operation if applicable, to the user.

You can imagine a lot of quality of life improvements built on top of that depending on your application: eg if the user holds granular undo and there are many combinable operations (eg the user drew a single stroke that is represented by hundreds of single pixel additions), you may snap to a single coarse undo. Or you can offer a visualization of the underlying operations and what they map to, etc.

(see sibling comment by ‘reificator)


That's a viable solution too, though it comes at the price of UX complexity. HN folks tend to undervalue simplicity because they love learning new features and want all the things. But often, the best user experience for the most people means sacrificing some operations that are technically useful but not enough to carry their weight.


Yup, ultimately the balance between simplicity and technical operations available will depend on one’s own specific use case.

That said, for technical applications, I think it makes sense to expose as much of your features as possible in terms of composable, atomic units and operations.

If Cmd-Z maps to a black box “undo” command, then anything on top of that will seem like it comes at an interface complexity cost.

If, however, Cmd-Z is a configurable shortcut like any other that, by default, happens to send a “undo 1 user operation” message to a “history” module, that’s a different story. Now your users can modify it to be “undo one high level operation” instead, or “undo all consecutive operations that are the same in kind”. Or perhaps they want Cmd-Z to undo the last discrete operation, and Cmd-Alt-Z to undo the last logical operation. Or maybe there’s a strong temporal dimension to their work and they want the undo logic to take that into account.

Likely not the kind of thing you’d want for a mobile photo sharing app meant for a wide audience; but maybe the kind of thing you’d want for a complex, specialized data processing tool on the desktop.


I feel like they should've just turned it into a feature. Remove the crashing bit, allow people to do the undo zooming. Not every bug needs to be completely fixed, and it's something game developers do too much. Unintended behaviour that has cool gameplay effects or are just plain fun are removed because the developer didn't intend it ... even though players like the "bug". It's one of the reasons why I really don't like Blizzard anymore, and one of the things the Warframe devs did really, really right.


That idea is the basis for the entire game of Goat Simulator: only fix crashing. Every other bug is hilarious. The game is basically a conglomeration of bugs. Its also one of my kids' favourite games of all time


I am a DM. For this campaign, your character choices are limited to:

[CPU, Guest, Anonymous, Player 1, Player 2, User, Random, "", undefined]


I fight for the Users!


Relevant xkcd: https://xkcd.com/1963/


Whatever could he mean by the mouseover text ...


Maybe "xkcd"? Not sure.


Parent was making a joke about their own name.


So... the backend of this game queries the database even if the user name is NULL? And the CPU user uses a magic name 'cpu', which is not a reserved name? And apparently the backend is totally okay with a user name that doesn't exist in the database?

Either this story is just an ad, or this game has been really badly build and some h4x0r is going to have a field day with this.


Do you never write bugs?


>And apparently the backend is totally okay with a user name that doesn't exist in the database?

What do you think happens when a previously unregistered user creates an account


s/or/and/

I got the impression it's both an ad and a poorly implemented game.


> This is a silly artefact left over from when there were no real player accounts and everything was just drop-in-drop-out.

Doesn't sound that weird to me. It's sensible to iron out the core gameplay and make sure the game's worth pursuing before focusing on persistent user accounts.


This is literally that NULL license plate problem! I wonder how many other systems this bug may exist in.

(https://news.ycombinator.com/item?id=20676904)


Please don't use the username as your primary key for a user!

Usernames change. If your username can't change, you designed your system wrong.

Systems that are heavily persisted-comment-based at least have the excuse where changing a username would invalidate old comments referencing that user, but even GitHub still lets you change your username (if you link @-references to users, please store the user's ID in the backend text and only convert it back to a username when displaying; GitHub doesn't take this step but it should).

P.S. Hacker News, I'm looking at you.


Years ago I had a regrettable experience working for an alleged telco in London that perpetrated myriad sins against humans and technology alike. Their spin on this problem was that they'd decided very early on to use email address as the PK for their homespun all-things-to-all-people system.

Shortly after they had to add an email column to address the predictable customer requests, and within a few years roughly half the user base was logging on with an email address they no longer used.


Have Virgin Media services (UK). They asked me to create as many email accounts as many services I signed in. I dont use those email addresses anywhere else, just to access they pages to pay bills. Who are those programmers, where are they from and how much they get paid. :-(


Years ago people used their ISP’s email service for email and when thru consolidation or choices their ISP changed they got a new email address.

Now I find most people use an email provider and I don’t see a lot of ISP style emails


The funniest thing is I could not use my original email as it is already used somewhere in the system and I have no clue when it happened. :-)


If you have strong foreign key constraints you should be able to update the record and let the changes cascade to each affected table.


nearly every assumption I usually see baked into a user model is eventually invalidated. and adding caching columns like "num of actions" are pretty common too, but that tends to mean your whole (fat) row is frequently invalidated, thrashing a bunch of caches.

break apart your user tables! if you have constraints on pieces of info, put the constraints there, not on the user!


It sounds like you are under the impression that we don't rename accounts. We do.


I did figure that if I were to email hn@ and ask, you'd probably be able to rename my account, but this isn't exposed anywhere in the UI (or even the FAQ), and links to profiles are based on username rather than some internal ID.


Come on, user names don't change. Whether it's Hacker News (as you mention), a reddit username, a skype ID, or your gmail address, nobody expects the "username" to change, it is unique and can't be used if already taken, and everybody uses it as a unique ID on millions of websites without any issue.

In fact, I can't name a single service I've ever used (ever!) that lets me change my username.


Usernames changing is important in a world where peoples' identities change.

People transition and might not want a username based on their deadname. People get married or divorced and change their legal name, which can have ramifications on their usernames. People might just get older, and lose significance of old pseudonyms.


do you think hackernews should allow people to change their username?


if throwaway346392834 wants to become their normal username, sure. why not.

of course it can be used for abuse - so show the old values next to it / on their user page / etc. allow N changes / limit the frequency. etc.


>so show the old values next to it

this would remove one of the reasons cited: "People transition and might not want a username based on their deadname." (People go to great lengths to remove references to their "deadname" and consider any mention of it seriously offensive.)

However, despite my downvotes (-4) I am unconvinced by that argument and the other replies. I don't think it's important to do this at all.


You've acknowledged that people transitioning is a huge motivation to change username, and yet say you aren't convinced. Why not? What's the benefit to not allowing usernames to change?


if allowing a change in username, do you think you should or shouldn't make visible a list of past usernames somewhere?


People change usernames because they don't want to be associated with their old username anymore. We shouldn't force anyone to retain that association unless it's overwhelmingly in the public interest to do so. On sites with open user registration I can't think of any possible justification for that. It's only sites with closed userbases where you'd even be able to begin arguing for this, and even there I don't know what argument you could use that would justify it.


> In fact, I can't name a single service I've ever used (ever!) that lets me change my username.

Facebook? Twitter? Instagram? Any of the phone-number-based social apps (which have a poorer UX because of it, but still all allow changing usernames seeing as phone numbers change)? Also I believe Skype does allow changing usernames.


Hotmail Gmail Seriously why can’t people change their email and keep the mailbox. It’s not uncommon to pick a cute or funny email when you are a teen and want To change when you’ve all grown up


With an imap client you should be able to download emails from the old accounts and upload them on the new one.


you mention Facebook but isn't it just your display name that you can change? your username (the page listed under "username" if you tap your face in the Messenger app, or on the desktop web app, the page you're at if you click your icon with your name next to the search bar) doesn't change, does it? (maybe I'm wrong and it does.)


Facebook lets you configure both your Name (display name) and Username (the URL slug for your profile) separately. You can even edit your Username right from within Messenger if you want.


ok, didn't know this.


This was a big value point for Twitter in the early days (2008 and 2009 era). Identity is fluid.


Xbox Live lets you change your gamertag, and I believe PSN does as well.

Pretty sure you have to pay to do it, but there are definitely services that let you change your user name.


Stack Overflow


This bug is a design smell.

They have a "Player" module that can likely be controlled by a human or by an "AI" module. This is good design.

The problem here is likely that IO is tightly integrated with Player and every other module as a dependency. This is what can cause the bug to occur.

Proper design is for the "Player" module to never depend on IO as a dependency...

1. the player module should be able to output the next gamestate of a game given the action and previous gamestate.

2. The AI should calculate the action when given a gamestate.

3. IO should be a function that when given gamestate, it displays it on the screen, or saves it to the DB.

4. All modules should be unaware of the other modules.

No dependencies.

Likely the fix that the poster is doing doesn't involve separating the "Player" module from all knowledge of IO, but the fix he is doing is making AI a special case in the "Player" module. This speaks to all kinds of wrong.

Following these design patterns over a long period of time leads to code that is "tech debt" heavy and messy. It's an inevitable consequence for programmers who don't know how to design things. Also note that this is normal. I would say 99% of programmers don't know this and are likely doing some garbage like using dependency injection to make every module in the system depend on IO.


Apparently there's still a few more bugs left to catch - the game's sign up screen briefly flashes a form then simply goes blank for me.


That's the bug he wished he had caught. All those people from hacker news clicking through to the site but no new signups!


Calling this a "bug" is a stretch. Similar to saying `1 == 2` is a bug. Could've been prevented by using distinct ID's in your tables and query criteria. When assigning experience, authenticating, selecting user data, etc., use the user ID.

Usernames are just localized, vanity UUID's for client-side pleasure.


http://lalo.li/lsd/ is full of bugs. i made a version without glitches. it was only half as fun.


But... if you really regret taking this out, why not leave it? I don't see how it can do harm. I can imagine players linking the account's profiles to friends going "hah, look at this" and creating more publicity, and people being for either Guest or CPU and talking about it... fun for the players, and good for publicity. Why take this out?

And then the post ends there and suggests I should go play the game. But a lot of people already commented that it sounds like an ad.


There have been bugs I wish I hadn't caught for entirely different reasons. Mostly if you find them on Friday before a Monday release and have to crunch to fix it lol


I find it odd there's no user ID instead of the username. But what I find even more concerning is it's not sanitizing the username to protect against SQL injection.


How can you know that there's no sanitization just from this blog post?


I think OP is getting the wrong idea from the screen shot in the article. There's a pic of an SQL query being run from a terminal. They might be thinking that it's a screen shot from the actual code.



This looks perfectly fine? Are you referring to the fact that they don't escape special characters like ' in the string? With the proper interfaces, like using prepared statements (which this likely uses in the backend, if this is an actual SQL db), instead of putting queries together just by concatenating strings, escaping strings is not only unnecessary but actively harmful.



It looks properly sanitized to me. The DB library being used is creating prepared SQL statements underneath the hood.


The code is sanitizing the username by running a prepared SQL statement. It's not doing SQL string concatenation.


Agreed. The username is simply a human friendly representation of an internal unique ID use in the database. What if the user decides to change their name from "CPU" to "CPUZ"? They would lose all of their experience. I really the implementation is not as shown in the screen shot.


It most definitely is https://github.com/RoganMurley/Ring-of-Worlds/blob/master/se...

Unless, I read that wrong


The code you linked looks good to me. The Beam library handles this properly. Where you do think the injection issue is?


The screenshot is a SQL query. There's no SQL in the linked haskell source. I'm not sure what you're getting at.


Genuine question, if usernames are unique what is the problem with using them as the primary key of the table instead of an arbitrary value from a sequence, you also get the bonus of not needing a unique constraint on the username column.


this is just an ad?


It was a nice anekdote, all development will be linked to a project anyway, linking to it just makes sense. Doesn't seem this was targeting a wider audience than devs, and I don't think the main market of the game is devs anyway.


The post is lacking any interesting technical information. It is a bland fantasy about how a poorly implemented scoreboard could be exploited. Based on the dramatic title I expected a deep dive into a large corporation's code that resulted in dark secrets of the highest order. Instead I got an API that doesn't have validation...


Cut the guy some slack. You can get your fill of conspiracy theories elsewhere. I for one enjoy random bouts of small, shallow experiences like these.


Yet it has 145+ net upvotes. Not really the guy's problem that you don't like his post. Your beef is with fellow HN users who upvoted it, but what a waste of time and energy on your part. Relax and enjoy your day as you clock a little bit closer to death.


Almost every article anybody writes is an ad for one thing or another, and be it the person itself.

It's a nice story, and maybe you could just not grudge him a few thousand eyeballs.


maybe the author included it just so people don't come back asking "what was the game from the story" or "where can I sign up ?"

The article did not promise anything, no free xp, no gold coins - it did not even explain how the game works.


Think of it as non-zero-sum content. The anecdote is interesting enough to be worth your time but it also gives the author some attention on their game.


Pretty much.


ugh, vapourbug


The point of the story being...?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: