Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
SupSuper
Apr 8, 2009

At the Heart of the city is an Alien horror, so vile and so powerful that not even death can claim it.

Falcon2001 posted:

Isn't it probably better than writing your own? Like presumably the big libraries are going to be more familiar with the edge cases/etc. They're certainly bigger targets but like, I don't trust myself to know JSON deserialization security better than any of the big libraries.
I didn't mean "write your own serializer", but "I can see the appeal in using a simple serializer for simple data", given half of .NET's serializers had to be deprecated for being a security issue: https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide

Adbot
ADBOT LOVES YOU

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Falcon2001 posted:

Isn't it probably better than writing your own? Like presumably the big libraries are going to be more familiar with the edge cases/etc. They're certainly bigger targets but like, I don't trust myself to know JSON deserialization security better than any of the big libraries.

The biggest security problem in deserialization is allowing an attacker to completely take over your process with a corrupt input because you’re using a memory-unsafe language. Obviously this is very common in languages like C.

The second biggest security problem in deserialization is allowing an attacker to run arbitrary code in your process because your clever magical reflective deserialization library will happily run anything that looks vaguely like a constructor and/or setter. This is amusingly very common in almost the exact complement of the languages above.

The latter is not something that library authors can fix except by telling you to turn off the clever magical reflective features which are probably part of the reason you embraced the library in the first place.

Fundamentally, you cannot just not think about it. The closest you can get is when you’ve got a fully statically-typed value and you’re able to work with a deserialization library that uses static code generation techniques to recursively deserialize correctly-typed components using their standard deserialization API; then you just need to worry about more pedestrian deserialization problems, like versioning. But any sort of polymorphism throws a wrench back into it.

rjmccall fucked around with this message at 00:13 on Sep 24, 2022

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

SupSuper posted:

I didn't mean "write your own serializer", but "I can see the appeal in using a simple serializer for simple data", given half of .NET's serializers had to be deprecated for being a security issue: https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide

I worked on a project where were we needed a little performance in json serialization and deserialization and were like "gently caress reflection, let's just write the json serialization and deserialization by hand" and that poo poo worked just fine, performed well and we didn't have to patch the server when someone found out you could ddos a server using malicious json post requests.

When I was younger I reached for the library immediately every time - you'll see platitudes like "don't roll your own crypto", which isn't a BAD platitude, but I will say that in grad school, I used the SJCL for a crypto demonstration in one of my classes and actually found a bug in the library itself, and debugging that took an enormous amount of time to figure out, and I probably would've been better off rolling the crypto myself (probably not a typical experience, but it's always possible), so I'm becoming more and more sympathetic to the "not invented here, avoid libraries, gently caress it, write it yourself" crowd as I get older, even though they're often wrong. At the very least, having to using a library to do something should never make you happy.

DaTroof
Nov 16, 2000

CC LIMERICK CONTEST GRAND CHAMPION
There once was a poster named Troof
Who was getting quite long in the toof

rjmccall posted:

The biggest security problem in deserialization is allowing an attacker to completely take over your process with a corrupt input because you’re using a memory-unsafe language. Obviously this is very common in languages like C.

The second biggest security problem in deserialization is allowing an attacker to run arbitrary code in your process because your clever magical reflective deserialization library will happily run anything that looks vaguely like a constructor and/or setter. This is amusingly very common in almost the exact complement of the languages above.

The latter is not something that library authors can fix except by telling you to turn off the clever magical reflective features which are probably part of the reason you embraced the library in the first place.

Fundamentally, you cannot just not think about it. The closest you can get is when you’ve got a fully statically-typed value and you’re able to work with a deserialization library that uses static code generation techniques to recursively deserialize correctly-typed components using their standard deserialization API; then you just need to worry about more pedestrian deserialization problems, like versioning. But any sort of polymorphism throws a wrench back into it.

this is all great and true, but it all boils down to DON'T DESERIALIZE TO CODE, FOR THE LOVE OF GOD

Absurd Alhazred
Mar 27, 2010

by Athanatos

DaTroof posted:

this is all great and true, but it all boils down to DON'T DESERIALIZE TO CODE, FOR THE LOVE OF GOD

the wise man bowed his head solemnly and spoke: "theres actually zero difference between data & code. you imbecile. you loving moron"

DaTroof
Nov 16, 2000

CC LIMERICK CONTEST GRAND CHAMPION
There once was a poster named Troof
Who was getting quite long in the toof

Absurd Alhazred posted:

the wise man bowed his head solemnly and spoke: "theres actually zero difference between data & code. you imbecile. you loving moron"

if only

lord funk
Feb 16, 2004

Absurd Alhazred posted:

I would also suggest that if 100% of your students get the answer to your question wrong, it might be a problem with the curriculum leading up to the question, or the question itself, not the students.

Sorry I bailed from this thread ealier, my internet sucks here.

The login screen UI problem is a 10 minute teaser at the beginning of the course. The students are told that they *are* the game designers / developers, and can do whatever they want to make their game. i.e., they are a small studio making a game, and trying to create the best user experience. They are then shown the 'work-in-progress' game images, and told they can change it in any way.

After they finish we talk about how preconceptions can feel like requirements, even when they are not. Just because it's commonplace to have a login doesn't mean it should be an automatic decision.

And then we have a discussion about what to do if it *is* a requirement. Like, letting the user have a 'Quick Play' mode, or waiting until they want to sync their high score to the cloud before creating the account, etc..

Anyway it's a lot more fun than I made it out to seem, I promise.

Absurd Alhazred
Mar 27, 2010

by Athanatos

lord funk posted:

Sorry I bailed from this thread ealier, my internet sucks here.

The login screen UI problem is a 10 minute teaser at the beginning of the course. The students are told that they *are* the game designers / developers, and can do whatever they want to make their game. i.e., they are a small studio making a game, and trying to create the best user experience. They are then shown the 'work-in-progress' game images, and told they can change it in any way.

After they finish we talk about how preconceptions can feel like requirements, even when they are not. Just because it's commonplace to have a login doesn't mean it should be an automatic decision.

And then we have a discussion about what to do if it *is* a requirement. Like, letting the user have a 'Quick Play' mode, or waiting until they want to sync their high score to the cloud before creating the account, etc..

Anyway it's a lot more fun than I made it out to seem, I promise.

That makes a lot more sense than most of the discussion about it here, my contributions included.

DaTroof
Nov 16, 2000

CC LIMERICK CONTEST GRAND CHAMPION
There once was a poster named Troof
Who was getting quite long in the toof

lord funk posted:

Sorry I bailed from this thread ealier, my internet sucks here.

The login screen UI problem is a 10 minute teaser at the beginning of the course. The students are told that they *are* the game designers / developers, and can do whatever they want to make their game. i.e., they are a small studio making a game, and trying to create the best user experience. They are then shown the 'work-in-progress' game images, and told they can change it in any way.

After they finish we talk about how preconceptions can feel like requirements, even when they are not. Just because it's commonplace to have a login doesn't mean it should be an automatic decision.

And then we have a discussion about what to do if it *is* a requirement. Like, letting the user have a 'Quick Play' mode, or waiting until they want to sync their high score to the cloud before creating the account, etc..

Anyway it's a lot more fun than I made it out to seem, I promise.

Thanks for clarifying. That sounds like a good introduction.

champagne posting
Apr 5, 2006

YOU ARE A BRAIN
IN A BUNKER


lord funk posted:

Sorry I bailed from this thread ealier, my internet sucks here.

The login screen UI problem is a 10 minute teaser at the beginning of the course. The students are told that they *are* the game designers / developers, and can do whatever they want to make their game. i.e., they are a small studio making a game, and trying to create the best user experience. They are then shown the 'work-in-progress' game images, and told they can change it in any way.

After they finish we talk about how preconceptions can feel like requirements, even when they are not. Just because it's commonplace to have a login doesn't mean it should be an automatic decision.

And then we have a discussion about what to do if it *is* a requirement. Like, letting the user have a 'Quick Play' mode, or waiting until they want to sync their high score to the cloud before creating the account, etc..

Anyway it's a lot more fun than I made it out to seem, I promise.

See now that seems pretty great

Canine Blues Arooo
Jan 7, 2008

when you think about it...i'm the first girl you ever spent the night with



Grimey Drawer
I've finally escaped from the torture that is Python and Javascript. We are back in C++ and C#, where projects can scale and there is some structure and rules and real types - these things are not an inconvenience, it's a force multiplier at scale, folks.

My yearish long stint with Python has lead me to conclude that it is a toy language for toys. If your project is going to expand past oh, about 10k lines of code and you choose Python, you have made a poor choice. Yes, I know Netflix uses it for stuff and I'm super sick of hearing about it. Maybe we didn't leverage it well. Maybe we made bad decisions that I didn't recognize. Maybe I didn't give it a fair shake because I was immediately pissed off at the hoops you have to jump through to set up and debug environments on Python when this is such a solved problem with the concept of a Solution. I'm not so confident in my thoughts on Python that I'd insist on them in a serious setting, but I'm left with an extremely bad taste in my mouth from it. Duck typing is the absolute worst idea ever.

Javascript is an unmitigated disaster, although I get the feeling that's not really a controversial take.

I really didn't think I'd actually miss C++, but here we are...

cheetah7071
Oct 20, 2010

honk honk
College Slice
I made the jump from R to Python to C++ as the data science I was doing kept having bigger and bigger datasets to process and the number one thing I love about C++ is that you can write a loop without murdering your performance

tyrelhill
Jul 30, 2006
javascript did, does, and always will blow rear end. i use python a poo poo ton but primarily as a bash or automation replacement

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
I used python as a better sh when it shipped with macOS. Now I'm back to sh.

champagne posting
Apr 5, 2006

YOU ARE A BRAIN
IN A BUNKER


Canine Blues Arooo posted:

I've finally escaped from the torture that is Python and Javascript. We are back in C++ and C#, where projects can scale and there is some structure and rules and real types - these things are not an inconvenience, it's a force multiplier at scale, folks.

My yearish long stint with Python has lead me to conclude that it is a toy language for toys. If your project is going to expand past oh, about 10k lines of code and you choose Python, you have made a poor choice. Yes, I know Netflix uses it for stuff and I'm super sick of hearing about it. Maybe we didn't leverage it well. Maybe we made bad decisions that I didn't recognize. Maybe I didn't give it a fair shake because I was immediately pissed off at the hoops you have to jump through to set up and debug environments on Python when this is such a solved problem with the concept of a Solution. I'm not so confident in my thoughts on Python that I'd insist on them in a serious setting, but I'm left with an extremely bad taste in my mouth from it. Duck typing is the absolute worst idea ever.

Javascript is an unmitigated disaster, although I get the feeling that's not really a controversial take.

I really didn't think I'd actually miss C++, but here we are...

Netflix's business as successful as it is, is also extremely simple: Deliver video streams to people. The rest is just billings and convincing some coked up fucker in a suit that their special show should be on the Internet instead of only through satellite tv or whatever

Absurd Alhazred
Mar 27, 2010

by Athanatos
Has anyone had any experience with TypeScript? I've run into at least one software house which claims that it provides a lot of the benefits of a strongly typed language like C++ while still being able to run on the browser.

champagne posting
Apr 5, 2006

YOU ARE A BRAIN
IN A BUNKER


Absurd Alhazred posted:

Has anyone had any experience with TypeScript? I've run into at least one software house which claims that it provides a lot of the benefits of a strongly typed language like C++ while still being able to run on the browser.

it has loads of benefits of types languages but the huge downside of being married to JavaScript

ultrafilter
Aug 23, 2007

It's okay if you have any questions.


cheetah7071 posted:

I made the jump from R to Python to C++ as the data science I was doing kept having bigger and bigger datasets to process and the number one thing I love about C++ is that you can write a loop without murdering your performance

You have to write a lot of loops though.

Eldred
Feb 19, 2004
Weight gain is impossible.

Absurd Alhazred posted:

Has anyone had any experience with TypeScript? I've run into at least one software house which claims that it provides a lot of the benefits of a strongly typed language like C++ while still being able to run on the browser.

It does some pretty clever things to make JavaScript type safe (ish) without the need to add a lot of type definition boilerplate. The downsides are that (like was said) it’s still JavaScript and you definitely feel that any time fetching data is involved and you can’t necessarily guarantee that you receive what you expect.

If you have to work with JS for any reason, do use it, you can absolutely feel the difference even in solo dev projects. It also has the benefit of being a little more opinionated than vanilla JS and it’s well-supported in common packages.

Canine Blues Arooo
Jan 7, 2008

when you think about it...i'm the first girl you ever spent the night with



Grimey Drawer

Absurd Alhazred posted:

Has anyone had any experience with TypeScript? I've run into at least one software house which claims that it provides a lot of the benefits of a strongly typed language like C++ while still being able to run on the browser.

TypeScript is a commendable effort to make the best out of a bad situation, but the situation is just not salvageable.

If your choice is Javascript or TypeScript, I'd choose the latter every time.

Absurd Alhazred
Mar 27, 2010

by Athanatos
Appreciate the info! :)

Thankfully it doesn't seem like I'm going to be forced into webdev anytime soon, but who knows where a tech career will lead?

Bongo Bill
Jan 17, 2012

I disagree that Javascript is an unmitigated disaster, because it is mitigated by Typescript. It ain't great but it helps a lot.

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

Absurd Alhazred posted:

Has anyone had any experience with TypeScript? I've run into at least one software house which claims that it provides a lot of the benefits of a strongly typed language like C++ while still being able to run on the browser.

i've been using typescript since start of public release (about 10 years now)

a) typescript does make dealing with the javascript ecosystem much much better. i would never touch regular javascript in a project anymore, screw working with that.

b) typescript also works like helmets for football players in that the safety features end up being used to cause more grevious injuries. people used to throw out projects that were 100k loc javascript and actually make webapis because 100k of loc was considered too much for a front end, and now since it's easy to scale up a ts project, nobody cares, you end up with web pages that have literally 100+ mb of javascript framework, so this wonderful technology (typescript) has been used to enable some astoundingly braindead software.

QuarkJets
Sep 8, 2008

Canine Blues Arooo posted:

I've finally escaped from the torture that is Python and Javascript. We are back in C++ and C#, where projects can scale and there is some structure and rules and real types - these things are not an inconvenience, it's a force multiplier at scale, folks.

This may come as a surprise, but Python has the strongest typing of the languages you listed here, C++ included (C++ is usually a strongly-typed language but also gives you some foot-guns if you want to subvert it a little)

The area in which Python excels, and it owes much of its popularity to this, is as a glue language. In fields where Python is the far-and-away dominant language, such as data science and deep learning, the libraries are heavily leveraging other languages for performance, but a practitioner can develop purely in Python with virtually no performance hit because they're those C and Fortran backends. When someone points out that Netflix uses Python they don't mean as their sole language; they use Python to to tie together a bunch of C, Javascript, SQL, etc.

Basically what I'm saying is that with experience you learn that no language excels at everything, I sure as gently caress wouldn't want to build a web app or an application that leverages deep learning with C++

cheetah7071
Oct 20, 2010

honk honk
College Slice
I'm still happy to never again have to delve through numpy's documentation to dig up the exact function that does the loop I want in C++ instead of just, writing a loop in C++

Bongo Bill
Jan 17, 2012

C++ will grant you no relief, though you might mistake different terrible problems for no terrible problems.

C# is fine.

lifg
Dec 4, 2000
<this tag left blank>
Muldoon
When I was learning and building a project in typescript I spent a lot of time in their GitHub issues page, looking at tickets marked “can not fix” with reasons like “we have no way to track this,” or “tracking this would require too much work.” Eventually I learned to work around those. But Typescript feels hampered by being a types layer on top of JavaScript, instead of types being an integrated part of the compiler.

QuarkJets
Sep 8, 2008

cheetah7071 posted:

I'm still happy to never again have to delve through numpy's documentation to dig up the exact function that does the loop I want in C++ instead of just, writing a loop in C++

If you're reading numpy documentation to try and figure out some clever function to vectorize a loop for numerical computation then you should just write a for loop and and compile it with the numba @jit decorator instead

fritz
Jul 26, 2003

QuarkJets posted:

This may come as a surprise, but Python has the strongest typing of the languages you listed here,

Typing's got at least two axes, strong/weak and static/dynamic, and I assumed CBA was talking about the latter.

FlapYoJacks
Feb 12, 2009
Python is the best non-compiled language there is. Rust is the best compiled language.

Armauk
Jun 23, 2021


cheetah7071 posted:

the number one thing I love about C++ is that you can write a loop without murdering your performance

You're in the end game, and it's time to rewrite all that in Rust. ;)

cheetah7071
Oct 20, 2010

honk honk
College Slice

Armauk posted:

You're in the end game, and it's time to rewrite all that in Rust. ;)

I probably would have just learned rust in the first place if I had known when choosing a language that rust can link to C libraries. It didn't have maintained bindings for the libraries I needed so I wrote it off

Canine Blues Arooo
Jan 7, 2008

when you think about it...i'm the first girl you ever spent the night with



Grimey Drawer
Does Rust have any good GUI Frameworks? I know it has a lot of them, but QT is not exactly the peak GUI-making experience. One of the big thing that always makes me come back to C# is just WPF, which is still just miles ahead of anything else I've used. As it is, C# is my favorite compiled language by quite a margin, but I also haven't given Rust a fair shake yet.

For interpreted languages, I just really dislike what they do to projects and I just avoid them more and more. Even my smallest projects are usually in C# these days.

Falcon2001
Oct 10, 2004

Eat your hamburgers, Apollo.
Pillbug

Canine Blues Arooo posted:

I've finally escaped from the torture that is Python and Javascript. We are back in C++ and C#, where projects can scale and there is some structure and rules and real types - these things are not an inconvenience, it's a force multiplier at scale, folks.

My yearish long stint with Python has lead me to conclude that it is a toy language for toys. If your project is going to expand past oh, about 10k lines of code and you choose Python, you have made a poor choice. Yes, I know Netflix uses it for stuff and I'm super sick of hearing about it. Maybe we didn't leverage it well. Maybe we made bad decisions that I didn't recognize. Maybe I didn't give it a fair shake because I was immediately pissed off at the hoops you have to jump through to set up and debug environments on Python when this is such a solved problem with the concept of a Solution. I'm not so confident in my thoughts on Python that I'd insist on them in a serious setting, but I'm left with an extremely bad taste in my mouth from it. Duck typing is the absolute worst idea ever.

Javascript is an unmitigated disaster, although I get the feeling that's not really a controversial take.

I really didn't think I'd actually miss C++, but here we are...

I don't fully disagree with this, although I will say that working with Python professionally at a big software company, the trick is to heavily enforce style and typing through MyPy/Black/etc, which helps it scale a lot better. Being able to actually use your IDE to figure out what type something is, is absolutely a huge win, and honestly I do kind of wish that Python just had a typing-enforced version, because coming from C# to Python was initially great, quickly followed by 'aw gently caress, what the gently caress is any of this.'

JS has a lot of the same problems with Python but without any of the fun upside of Python's elegance and ease of use. It's just all the downside of both and I hate working with it.

Ranzear
Jul 25, 2013

Canine Blues Arooo posted:

Does Rust have any good GUI Frameworks? I know it has a lot of them, but QT is not exactly the peak GUI-making experience.

Anything worth using is backed by winit, best I can tell, so that's where I'd start my own search. I'm only in the Vulkan rendering stuff so far though. I would like to hear of a good widget handler for clickable menus and such.

duck monster
Dec 15, 2004

Volmarias posted:

Would his being a PM result in him no longer coding anything and also not being part of your chain? If so, it might be possible that they're trying to sideways promote him to someplace where he can be effectively ignored even if he cannot be fired or directly sidelined.

No. It would make him my boss, for all of the mimimum time it takes to see out my contract notification period, and likely the entire teams notification period. I've told the boss that I consider it a move that would be a company killer.

And the boss has now been made told the same by pretty much everyone on our team.

Also I sat down with the boss and demonstrated completely pwning a demo install of his "improved" TCP stack including burning down the database. The boss agreed to me running the new stack through the load tester even if new guy objects (He had been objecting for a while. Because the old stack was stable up to around 20K connections, (while I know from private tests the new one seems to start OOMing the VM after about 30 connections from all the race conditions and other horrors that happened when innexperieced people try and roll their own servers). New guy is informed this will be to test how it handles under 10-20K client conditions. I expect this to be a blood bath.

They might be transfering him out to the engineering team since he spends almost his entire time there instead of doing his job.

Good luck trying to terrorise our hardware guys with THAT level of coding incompetence, Our main embedded guy is a *lot* less polite than I.

Carbon dioxide
Oct 9, 2012

If TypeScript isn't strongly typed enough for you, instead you can use tooling that compiles a strongly-typed language directly into Javascript. Scala.JS comes to mind, although I've never had the chance to work with it myself so I'm not sure how well it holds up.

champagne posting
Apr 5, 2006

YOU ARE A BRAIN
IN A BUNKER


Absurd Alhazred posted:

Has anyone had any experience with TypeScript? I've run into at least one software house which claims that it provides a lot of the benefits of a strongly typed language like C++ while still being able to run on the browser.

Here's a good time I had with TypeScript:

champagne posting posted:

typescripts type system is neat, but filled to the brim with foot guns

edit: will post terrible examples when I'm at work tomorrow and hopefully remembers. One thing that comes to mind is primitives as types. Basically:

code:
interface BaseGlass: {beverage: string, full: boolean};

interface WineGlass extends BaseGlass: {beer: false};

interface BeerGlass extends BaseGlass: {beer: true};

export type Glass = BaseGlass | WineGlass | BeerGlass;
Now when you want to do:

code:
const thirst: Glass = {beverage: string, full: boolean, beer: true}
You will get a typescript error, because true cannot be assigned to false. The property is not a boolean, it is either true or false, but it never intersects.


edit II: My coworker does this all the time and I loving hate him for it. He's clever as hell and needs to write code to live and it's all over the code base. My only solace is my last day is end of March.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

champagne posting posted:

Here's a good time I had with TypeScript:

Unless I'm misunderstanding you, this one doesn't seem to have been applicable for a while: https://www.typescriptlang.org/play...AE1AG50uYCGkiAA. It works at least as far back as TS 3.3, which is over three years old. I think the type unification was improved somewhere around that time.

I don't disagree that TS is full of footguns though, especially when you interact with libraries that lack built-in type information. For example, it's very easy to end up with a string inside a variable of type number or vice-versa. That stuff can come as a real shock when you're used to languages like C#/C++. You know, stuff like this:

TypeScript code:
interface Foot { name: 'Your foot', toeCount: number; }
interface Enemy { name: string; }

function shoot(enemy: Enemy): void {
  console.log(`${enemy.name} has been shot!`);
}

function dumbFunction(_enemy: Enemy): Enemy {
  const foot: Foot = { name: 'Your foot', toeCount: 5 };
  return foot as any;
}

let enemy: Enemy = { name: 'PHP' };
enemy = dumbFunction(enemy);
shoot(enemy);
You can guess what the output is.

Admittedly most languages have ways to gently caress around with the types if you get creative, but it happens a lot more in TS because of the ecosystem.

Adbot
ADBOT LOVES YOU

Osmosisch
Sep 9, 2007

I shall make everyone look like me! Then when they trick each other, they will say "oh that Coyote, he is the smartest one, he can even trick the great Coyote."



Grimey Drawer

LOOK I AM A TURTLE posted:

TypeScript code:

function dumbFunction(_enemy: Enemy): Enemy {
  const foot: Foot = { name: 'Your foot', toeCount: 5 };
  return foot as any;
}


Wow you just made me angry irl

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply