[HN Gopher] What it feels like when Rust saves your bacon
___________________________________________________________________
What it feels like when Rust saves your bacon
Author : lukastyrychtr
Score : 186 points
Date : 2022-06-24 06:43 UTC (16 hours ago)
(HTM) web link (smallcultfollowing.com)
(TXT) w3m dump (smallcultfollowing.com)
| rs_rs_rs_rs_rs wrote:
| Animats wrote:
| _" Each method is defined on this Context type that carries some
| common state, and the methods tend to call one another."_
|
| This is classically a problem of GUI systems, where you have a
| large number of interlinked on-screen objects constantly
| undergoing modification.
| BiteCode_dev wrote:
| And hence the general recommendation of having a single
| direction in your input/render cycle:
|
| - wait for input
|
| - a dispatcher take any input and turn it into a queue of model
| update actions
|
| - pop queue to perform latest model updates.
|
| - trigger a full tree rendering, passing the new model
|
| - start again
|
| So:
|
| - the model is a dumb static data structure
|
| - the dispatcher is the responsible for model updates and is a
| single entry point for the data flow
|
| - the UI and the model don't know about each other
|
| That what ELM, react and so on do now. Monodirectional MVC.
| It's hard to optimize the rendering though, but it's way easier
| to reason about when concurrency gets high.
| mejutoco wrote:
| > - trigger a full tree rendering, passing the new model
|
| I agree the Elm model makes it easy to reason about it.
|
| Just because we pass "the state of the world" each time
| instead of mutating it, does not mean that we need a full
| tree rendering. That is an implementation detail.
|
| We can update just the relevant part. If we think of it
| mostly as pure functions a lot of it is easier to memoize and
| -- for same input -- it is possible to return the same output
| straight away.
| BiteCode_dev wrote:
| That's what I mean by hard to optimize. Memoization is hard
| to get right, because if you compare only by value, it can
| be slow, but if you compare by identity, the cache can take
| a lot of memory.
|
| And of course, forcing a purely immutable model comes with
| its own unique challenges.
| lbriner wrote:
| I have only a small dabbling in Rust and it was to create a
| Postfix milter. What was awesome was that someone had already
| written a Rust crate so that I didn't have to do anything too
| horrific. The compiler on Ubuntu just worked as expected but, of
| course, as something that is not standalone, Rusts strong type-
| checking did not save me from writing something that didn't work.
|
| Part of the confusion is the very confusing (for a noob)
| difference between String and &str and as someone who has written
| C and C++, I don't have a problem with understanding references
| and addresses but I didn't find a very good explanation. This led
| me to writing code using the only way I could get it to compile
| that didn't crash at runtime (which was nice!) but it also didn't
| work.
|
| The second issue was that being something plugging into an
| external daemon, at the interface level, we were getting a raw
| pointer and had to convert it into a string to use it. I tried so
| many combinations but couldn't get it to work but thanks to the
| maintainer of the Rust crate (who obviously knew what he was
| doing) he told me where my code was wrong and I fixed it.
|
| So I guess good in that there were probably no horrific bugs,
| although this is much like C# or possibly Java. But yes, the
| strong checking doesn't stop things from not working.
| darthrupert wrote:
| Rust's safety features have never been its main selling point for
| me. Modernity and (recently) momentum are. That it's impossible
| to author certain classes of bugs is a nice bonus.
|
| That said, I never want to see another rounding bug in financial
| statements that happened because some piece of code implicitly
| converted a string to a float and it kinda almost worked every
| time. To quote a cliche, I'm too old for that shit.
| darthrupert wrote:
| (Probably float to string and back, actually. Some mess like
| that anyway)
| cobbzilla wrote:
| When I was first learning Rust, it was exactly this sort of
| lifetime issue that tripped me up and frustrated me, until I
| finally saw the light and understood how things work.
|
| Yes, the article is overly technical and detailed, but it
| captures very well the eureka moment of understanding Rust's
| memory management. Some aspects are subtle yet profound.
|
| I am always happy to take a little more pain at code-writing and
| compile-time in exchange for more safety guarantees at run time;
| Rust is great in this regard.
| shuger wrote:
| This article is super overcomplicated. All it had to say was that
| rust tells you when you keep reference to on stack variable after
| it goes out of scope. Context provided adds nothing.
|
| I must say - as someone who doesn't use rust - I haven't had this
| type of issue in years, and when I did it wasn't hard to debug.
| You get corrupted data, set data breakpoint and in the provided
| example you will see it being modified by unrelated operations on
| stack. From there there is only one conclusion. Authors reactions
| seems to be a bit exaggerated.
| atoav wrote:
| It all depends on the complexity of your application. The type
| of guarantees Rust offers in my experience becomes
| exponentially more useful as your application grows in size.
| DrBazza wrote:
| Just because Rust, in particular, compiles successfully,
| that's no guarantee that the code isn't complex and difficult
| to understand. I can write a complex badly designed app in
| any language. Similarly I can write simple well designed
| large applications in any language too.
| ChadNauseam wrote:
| Yeah, but that doesn't mean all languages are created equal
| in that department. Let's take this pseudocode:
| int a = 0; if (findindex(mylist, myvalue, &a)) {
| // dostuff with a }
|
| Here, findindex returns false if it can't find the value.
| The problem is that there's nothing forcing you to use the
| if, you can just forget it and you'll be left with
| incorrect code. In Rust, this type of error is impossible
| to make by accident, because the findindex function would
| return an Option, and you have to explicitly handle both
| cases (or explicitly say you don't care about one of the
| cases).
|
| Things like that, along with the lifetime system, make it
| easier to write good code. It's like saying that it's
| possible to destroy your foot with a shotgun and with a
| pencil - it's possible, but it's a lot easier do to by
| accident with the shotgun.
| Daishiman wrote:
| This fallacy gets repeated over and over again and it
| doesn't make it any less false.
|
| Languages are tools and some tools are actually better-
| built than others. If we can claim that a language like
| Brainfuck makes writing clear code extremely difficult, and
| Python or Rust make writing clear code easier, we've
| already established that there's a spectrum for language in
| expressiveness and clarity.
|
| Eliminating entire classes of bugs makes for better
| understanding.
| lelanthran wrote:
| > It all depends on the complexity of your application. The
| type of guarantees Rust offers in my experience becomes
| exponentially more useful as your application grows in size.
|
| Sure, but the development pattern that get used for larger
| applications typically don't benefit from Rust's additional
| safety; for one you're going to be using a garbage collected
| language.
| MaulingMonkey wrote:
| > for one you're going to be using a garbage collected
| language.
|
| I wish it were true, but promise you it is not. As a
| counterpoint, I point to most "AAA" gamedev and OS
| development.
|
| In gamedev it's even a bit flipped: The smaller indie
| gamedevs can pay the GC hit for Unity's C#, web JS,
| actionscript flash back in the day, etc. - not much working
| data, not much garbage. Larger scale titles start missing
| vsync and having horrible stuttering when GCs are thrown
| into the mix too brazenly - they're still used on smaller
| scales (embedding browser tech for UI, limited scope
| scripting, etc.) but they have a lot of native, non-GCed
| code.
| MaulingMonkey wrote:
| This indeed. Small local console app running on trusted data?
| Maybe an hour to track down some memory corruption if you're
| particularly unlucky, in which case shuger's kind of got a
| point: who cares?
|
| Large network-exposed app? Individual memory corruption
| heisenbugs have taken me _weeks_ to track down (and weeks
| before that for QA to create a reliable repro for) - a needle
| in a huge haystack. They often predate my employment - having
| lurked semi-silently for who knows how long causing who knows
| how many unreported crashes. When release dates slip because
| of bug backlogs filled with memory safety related crash bugs,
| when ~70% of many vendor CVE reports are down to memory
| safety issues [1][2][3], and when you personally have to deal
| with the fallout of all that: shuger 's point completely and
| utterly evaporates.
|
| [1] https://msrc-blog.microsoft.com/2019/07/18/we-need-a-
| safer-s...
|
| [2] https://www.chromium.org/Home/chromium-security/memory-
| safet...
|
| [3] https://langui.sh/2019/07/23/apple-memory-safety/
| SloopJon wrote:
| > All it had to say was that rust tells you when you keep
| reference to on stack variable after it goes out of scope.
|
| The author isn't just telling you that Rust is awesome because
| it tells you something, he's acknowledging the frustration in
| learning how to listen to the compiler.
|
| It's kind of like Jerry Pournelle describing the ups and downs
| of USB by documenting an epic journey that all started with
| trying to scan some handwritten notes for his next novel using
| a Canon scanner he borrowed from Alex that he's just now
| getting around to reviewing, because the pins of the parallel
| port are too bent to use the old Epson. Okay, so maybe it was a
| little overcomplicated.
| est31 wrote:
| > You get corrupted data, set data breakpoint and in the
| provided example you will see it being modified by unrelated
| operations on stack.
|
| That's provided that you can even reproduce the issue well,
| especially in an instrumented build which might be way slower
| than the non instrumented one. Often you get bug reports like
| "crash after one hour of usage" where basically every feature
| of the app has been heavily used by multiple users. Rust
| applications might still crash but they crash safely, which
| means your error messages are more meaningful.
| ekidd wrote:
| > _All it had to say was that rust tells you when you keep
| reference to on stack variable after it goes out of scope._
|
| That's the root cause, but it's not the interesting bit.
|
| The code in the article comes from a production compiler. And
| normally, the AST (abstract syntax tree) is a single data
| structure output by the parser. Ownership is simple: the entire
| AST has the same lifetime, and it's managed by a caller. This
| should be easy, right?
|
| But it turned out that there was a piece of code that
| _sometimes_ "synthesized" extra, temporary AST nodes. And these
| nodes had a shorter lifetime than the rest of the AST.
|
| These are vicious bugs. You have some long-standing convention
| about how things work, but one little piece of code makes an
| exception (often for excellent reasons). Then _another_ module
| decides to make an aggressive optimization that relies on the
| original assumption. But that assumption is now true only 99%
| of the time.
|
| It's a communication failure, and it might take years to
| actually turn into a bug. And that bug may manifest as
| extremely rare memory corruption that shows up in automated
| crash reports.
|
| Running down this kind of phantom memory corruption is one of
| the most frustrating things I've ever done. It often involved
| spending weeks staring at minidumps, looking for interesting
| patterns in crashes. There's that horrible moment when you
| realize that 20% of your crashes occur within a thousand
| instructions after a particular font-rendering function reports
| an error, accidentally corrupting the exception-unwinding
| machinery.
|
| And sure, I get it. Maybe your team is simply good enough that
| nobody ever makes a mistake like this. But if so, they're
| exceptional. I've worked on amazing teams that still get bitten
| by subtle miscommunications and misunderstandings.
| ArrayBoundCheck wrote:
| It's unfortunate how many upvotes this got from the title
| cbarrick wrote:
| Earlier this month we integrated a C++ library written by my
| team with a server written by another team.
|
| We saw the data corruption, and we knew it was a reference
| issue, but it took quite a bit of effort to track down. The
| cause was confusion around string_view and string&, with
| different behavior when you pass each to a new thread.
|
| Rust would have caught this much earlier and saved 3 days work.
| lelanthran wrote:
| Agree; this is not an issue that slows down my development or
| bughunts.
|
| You can get a long way towards safety without learning Rust.
| It's those rare cases that will get you.
|
| It's a trade-off; take the time to learn the language and
| deliver later, or just use what you already have to deliver a
| product now.[1]
|
| [1] During a Rust discussion some years back, when I was at a
| different company, on a specialised and large-ish product
| written in C++03.
|
| I went through about 3 years of tickets (limited to only the
| bugs reported). No open ticket was older than a few weeks. Out
| of maybe 1000 bugs, only a single one was something Rust would
| have prevented. I would think that most mature products will
| have similar stats, so the trade-off is not as obvious as it
| looks to be on the surface.
|
| Deliverables matter.
| nemothekid wrote:
| > _I went through about 3 years of tickets (limited to only
| the bugs reported)_
|
| This statement is meaningless without any insight on how bugs
| were created. If the bug reports exclusively dealt with
| "happy-path" or "business logic QA", then of course you won't
| see any CVEs. Did the use of fuzzers or address sanitizers
| create bug reports? Were these tools even used? If not, the
| claim that only one of 1000 bugs were memory safety issues
| isn't credible; you weren't looking for them so of course you
| didn't find them.
|
| I think it says a lot when almost every C++ developer claims
| to have a higher quality code base compared to say Linux or
| Chromium when it comes to memory safety errors.
| Daishiman wrote:
| What is it about C++ as a community where most average devs
| claim an inhuman level of proficiency but only the coders
| with experience in real critical codebases have the
| humility to claim that without extremely strict coding
| practices and extensive use of fuzzers we're barely smarter
| than apes at churning out safe code?
| vgel wrote:
| It probably depends on project type and how complex your
| ownership models are, but that doesn't really track with
| large projects having a majority of their CVEs be memory
| safety issues that are far less likely in Rust[1] (e.g.,
| https://www.chromium.org/Home/chromium-security/memory-
| safet...)
|
| [1] I say far less likely because obviously it's possible
| with unsafe Rust, but I've never had one happen, seen one
| happen in real code, or been affected by part of a dependency
| tree having one.
| snovv_crash wrote:
| CVEs are a tiny, tiny fraction of bugs.
| lelanthran wrote:
| I'm not saying that a large number of CVEs _won 't_ be
| prevented in Rust, I'm saying that so few bugs are CVEs
| that the trade-off is not always worth it.
|
| If you have 1000s of bug reports, of which 5 are CVEs, and
| then have 3 of those 5 be preventable, most dev teams are
| still going to consider the cost/benefit of going through
| the pain of developing a long-term product in Rust, or of
| switching to Rust altogether.
| girvo wrote:
| I suppose it comes down to risk assessment; if those CVEs
| are critical "fix this now or the world catches fire",
| then their relative infrequency seems to be outweighed by
| their impact, no?
| lelanthran wrote:
| > I suppose it comes down to risk assessment; if those
| CVEs are critical "fix this now or the world catches
| fire", then their relative infrequency seems to be
| outweighed by their impact, no?
|
| No.
| bschwindHN wrote:
| > of which 5 are CVEs
|
| Those 5 are just the ones you know about...
| lelanthran wrote:
| > Those 5 are just the ones you know about...
|
| It's pointless making a cost/benefit analysis on things
| that probably don't exist.
| renox wrote:
| I agree with you on the first point, but I totally disagree
| with you on the second point: sure if you know how to reliably
| reproduce an issue it isn't complicated to debug, but this kind
| of issue can be difficult to reproduce, can create silent
| issues..
| bestouff wrote:
| Yeah no. In my experience, when several people commit to a
| common C/C++ codebase this kind of issue become really
| exhausting when it happens more than once, and the symptoms may
| be so subtle it's a bitch to debug.
|
| Rust lowers your mental load. You spend more time being
| creative and way less time debugging "obvious" (or not)
| mechanical problems (reference not-on-stack-anymore variables,
| use-after-free, concurrent write access and all kind of
| compiler undefined behavior). That why garbage collected
| languages are so successful (they let you concentrate on the
| business logic) and for the first time it's available in a
| system language.
|
| Everything that can be done by your computer should be done by
| your computer. You should leave your precious brain cells
| available for the important stuff.
| phendrenad2 wrote:
| Nope. In my experience, Rust saves you from very common
| obvious errors that junior programmers make, certainly not
| 10x programmers who have been writing C for a long time. It's
| great when you're starting out (which is why it's massively
| popular with new graduates or people who are just learning to
| program), but at some point it's questionable if the hand-
| holding Rust gives you is worth the extra development time
| overhead, more complex syntax, etc.
|
| It also depends on what you're writing. If you're writing
| cryptographic routines, or protocol handshaking, the
| tradeoffs are heavily weighted in Rust's favor.
| shuger wrote:
| I work in probably what is considered one of the least "safe"
| languages: C++
|
| The issues that Rust is supposed to help with are simply not
| what we spent time on. All the bugs reported are pretty much
| exclusively root caused to "business logic".
|
| From recent time I can recall only one that was a programming
| mistake and not architecture/business logic related. It was a
| missing break in a switch that already had some fallthroughs
| so it didn't look incorrect at a glance.
|
| I do understand what Rust is supposed to provide but in
| practice it's simply an extremely minor source of bugs.
| jackmott42 wrote:
| I see many C++ programmers say stuff like this, and maybe
| it is the case that studios exist which can do C++ without
| mistakes related to memory management or sigils and so on,
| but I also observe that:
|
| 1. High quality teams like the Linux kernel team and
| PostgreSQL, do periodically have serious security bugs that
| are things Rust would have caught.
|
| 2. I see sometimes C++ instructors making the same claims
| you do and then spending half of a lesson tracking down a
| memory mistake, (Casey Muratori) or in the same month a
| tweet from a game engine developer saying they don't really
| see the value of garbage collection and then tweeting about
| how they spent 48 hours tracking down a memory mistake. (of
| course, for a game engine that is what you have to do
| sometimes!)
|
| There are however valid questions, like if Rust slows down
| your development say, 5%, would you get more net safety
| from spending 5% more time testing/fuzzing c++ code
| instead? etc.
| melissalobos wrote:
| > High quality teams like the Linux kernel team
|
| Which very notably does NOT use C++.
| csdreamer7 wrote:
| Nor does Postgres.
| 3a2d29 wrote:
| > High quality teams like the Linux kernel team and
| PostgreSQL, do periodically have serious security bugs
| that are things Rust would have caught.
|
| Safe rust would have caught. If you had to drop into
| unsafe to do what they did, the serious security bugs
| would still have happened.
| jackmott42 wrote:
| A fair point, though the few security issues in recent
| years I've looked at were not the kind of thing you would
| turn to unsafe rust for. But I've certainly not done a
| broad enough sampling to say what % of cases are like
| that.
| 3a2d29 wrote:
| To be fair, I am sure Rust catches a fair amount
| (compared to C++ which would catch 0). I just think that
| phrasing rust has having 0 memory errors can be a tad
| inaccurate.
| jesse__ wrote:
| I'd venture that the development slowdown from using rust
| is closer to 50% than 5%. Even just compile times
| probably slow down that much, not to mention you have to
| write (sometimes) as much as 10x code to express
| yourself.
|
| The specific exercise I have in mind is a lockless thread
| queue. < 20 lines in C .. ~200 lines in Rust.
| jackmott42 wrote:
| I'm sure there is a ton of variance. I have done some
| Rust projects where I run into absolutely no safety
| complaints from Rust because it just isn't the kind of
| code that does anything the borrow checker cares about.
| For those development time ends up typically faster than
| C/C++ due to various syntax and tooling niceties.
|
| Other projects will really get into domains where you
| have to work hard to satisfy the borrow checker and it
| can slow you down a lot. In a real application you won't
| be writing lockless thread queues for a big % of the
| time. But then for a real application the compile times
| will start to weigh on you more. (Though, C++ does not
| always compile fast either unless some care is taken to
| be sure it does)
| Yoric wrote:
| My anecdotal experience is the opposite.
|
| I write code much faster in Rust than in C++. Part of it
| is thanks to the type system - fewer opportunities for
| dev errors means that I can produce code that is more
| concise, spends less time handling runtime errors because
| I can have static guarantees that they have already been
| handled somewhere, etc. Part of it is #[derive(...)],
| great documentation, Cargo and other QoL components of
| Rust.
| pkulak wrote:
| A lockless thread queue (not entirely sure what that
| would be, sorry; a queue in front of a pool?) seems like
| the kind of low-level library that could be written with
| liberal use of unsafe. No need to flagellate yourself on
| the altar of compile-time safety.
| kajaktum wrote:
| >The specific exercise I have in mind is a lockless
| thread queue. < 20 lines in C .. ~200 lines in Rust.
|
| Do they have an equivalent API? Rust does have a hard
| time explaining very, very low level stuff that you'd
| have to do unsafe and various magicks. But once you get
| the unsafe details right, the consumer API for them tends
| to be extremely rigid and fool proof.
| [deleted]
| __jem wrote:
| > The specific exercise I have in mind is a lockless
| thread queue. < 20 lines in C .. ~200 lines in Rust.
|
| Why is this your exercise you have in mind though? This
| is such a bad argument. Like, yes, if you work at
| doublylinkedlist.com where your entire job is writing a
| new linked list implementation every day of the week,
| Rust might be a bad choice. But that's not what any kind
| of commercial enterprise actually looks like. If I saw
| you writing a lockless thread queue at work, I'd tell you
| to stop wasting time.
| jandrewrogers wrote:
| > High quality teams like the Linux kernel team and
| PostgreSQL
|
| Neither of those code bases are C++, which significantly
| dilutes your point. A major benefit of modern C++ is that
| it is _much_ safer than the language Linux and PostgreSQL
| are written in.
| Daishiman wrote:
| Chromium _is_ written in C++, has some of the best coders
| and one of the best-tested codebases in the world.
| They're still finding zero-days based on exploits due to
| the language's failings.
|
| There's a reason Mozilla has decided that all parser code
| should be moved to Rust ASAP.
| boris wrote:
| > There are however valid questions, like if Rust slows
| down your development say, 5%, would you get more net
| safety from spending 5% more time testing/fuzzing c++
| code instead? etc.
|
| I think a similarly valid question is how often you
| resorted to dynamic allocations just to get the borrow
| checker off your back. If your Rust version uses 5% more
| dynamic memory (with the corresponding performance and
| memory footprint penalty), is it perhaps worth staying
| with C/C++ and spending more development time on
| testing/fuzzing?
| smolder wrote:
| If you're willing to jump back to C++ to get around the
| borrow checker strictness, couldn't you just use Rust's
| unsafe block where you're sure it won't result in a bug?
|
| Is it harder to fuzz Rust? Honest question, because
| fuzzing is something I occasionally read about but am not
| practiced in.
| duckerude wrote:
| I've found it very easy to get started with fuzzing in
| Rust using cargo-fuzz. I didn't do anything very
| advanced, and my closest point of reference is testing
| Python with Hypothesis, but it did turn up bugs.
|
| Here's a Rust fuzzing story from yesterday:
| https://hacks.mozilla.org/2022/06/fuzzing-rust-minidump-
| for-...
|
| It claims that Rust is particularly suitable for it
| because integer overflow panics in debug builds (and out
| of bounds indexing always panics), which sounds
| reasonable.
| duckerude wrote:
| Some people make the opposite claim: Rust lets you get
| away with less dynamic allocation (and more data shared
| between threads) because you can rely on the compiler
| checking your work.
|
| The effect might be positive or negative depending on the
| circumstances.
| jackmott42 wrote:
| That is a fair thing to wonder about, but at the moment
| most of the design decisions Rust pushes you toward tend
| to be better for performance on modern hardware. For
| instance using an array based arena to store a graph,
| instead of the traditional allocation of a chunk of
| memory per node on the heap. Or just keeping more stuff
| on the stack.
| ostenning wrote:
| Can you elaborate on the proficiency of your dev team, is
| this with juniors etc? Is it a large team? And what is the
| complexity of the project? I think this is important
| information
| shuger wrote:
| GPU driver, most devs are senior. Hundreds of thousands
| of lines of code in the "slice" my team is interested in.
| Team for our component has on it's own has probably over
| 40 people.
|
| Driver should be even more prone to programming bugs
| because most of it is about manipulating data in raw
| "untyped" memory.
| Daishiman wrote:
| My experience with GPU drivers then is that your code is
| likely buggy AF and your team is in denial.
| the_mitsuhiko wrote:
| GPU drivers are also some of the most buggiest stuff out
| there I used. When I worked in Games we routinely managed
| to make the GPU drivers crash which thankfully at the
| time was already no longer taking down your engine
| machine.
| bestouff wrote:
| My manager told me exactly the same thing as you do; after
| I found a few UB in its code in the first 2 weeks he
| changed its stance.
| josefx wrote:
| I had to deal with a senior dev. that gave me a talk
| about seniority after I ran valgrind over our software.
| Guy was so deep into the whole senior dev. power trip
| that he blamed third party libraries for his bugs, dev.
| tools for "incorrectly" identifying his bugs and wrote
| more bugs to work around his other bugs.
|
| Finding and fixing issues in C++ code can be easy with
| the available tools, getting people to use them on the
| other hand can can be like talking to a wall.
| darthrupert wrote:
| That sounds more like an expert beginner than senior.
| im3w1l wrote:
| Sounds like someone who senses his place in the hierarchy
| is threatened.
| nemothekid wrote:
| > _The issues that Rust is supposed to help with are simply
| not what we spent time on._
|
| There could be plenty of bugs in your codebase but just
| because you don't spend time on them doesn't mean they
| don't exist. Hundreds of millions of people used OpenSSL
| everyday for 2 years after the Heartbleed bug was
| introduced. It didn't cause any obviously broken code until
| someone exploited it to read credit card numbers off of a
| remote server.
| [deleted]
| Agingcoder wrote:
| In practice for you. Where I am, things are very different!
| Buffer overflows and memory corruptions, threading issues,
| uninitialized variables, etc appear on a very regular
| basis, and end up being very difficult to debug, mostly
| because the moment where you corrupt memory and the moment
| it triggers a bug can be very far apart.
| strictfp wrote:
| I've worked in a variety of languages, and returning to a
| c++ project recently I do see that we spend a lot more time
| thinking about how to write the code in a way that avoids
| problems. Meaning that there's a lot more architecturing
| required to reach a sane state.
|
| We have a sister product written in a dynamic language, and
| sometimes we have identical functionality.
|
| I've noticed that when a change is discussed, the c++ gang
| has architectured themselves into the current solution and
| therefore have a much harder time making changes.
|
| So for that reason I think it's easy to overlook these
| complexities when you're working in c++ alone; they feel
| natural and are just part of how you work. You forget that
| a lot of this architecturing just isn't necessary in a lot
| of other languages.
| jstimpfle wrote:
| Maybe I'm wrong, but I believe that most of the
| architecting that you describe would be effectively what
| you do with regards to performance as well: Minimizing
| change of ownership, moving to a system with more static
| allocations with fewer "objects" that are linked into a
| variety of subsystems.
| cyber_kinetist wrote:
| ...and when you do need a large number of dynamically
| allocced/deallocced objects, then using indices to arrays
| instead of pointers. Which kinda defeats the purpose of
| using the Rust borrow checker...
| strictfp wrote:
| Yes, that's true. In a sense, c++ requires good code
| structuring.
|
| That's also part of why I enjoy returning to c++, the
| people involved know how to structure code and create
| clean architecture.
|
| That said, sometimes c++ does get in the way. Creating
| trees or graphs can be cumbersome, and IMO it's very
| biased towards virtual methods to solve polymorphism.
|
| Extending lifetimes by pooling or similar is also quite
| common, and is in my eyes sometimes overdoing it. If you
| for instance use Rust, you can be a lot more confident
| that the compiler catches these issues, and be more
| conservative and efficient in the solution.
| jhgb wrote:
| > and IMO it's very biased towards virtual methods to
| solve polymorphism.
|
| Is it? These days I'd expect C++ to be very biased
| towards using templates for polymorphism. After all,
| templates are a thing that C++ provides with
| functionality that other languages often lack, whereas in
| the field of virtual methods/"dynamic dispatch OOP" C++
| severely lags behind other languages. Choosing between
| two features of a language and using exactly the one that
| is worse in comparison to your competition feels wrong to
| me.
| FpUser wrote:
| I do not think C++ "lags severely in the field of virtual
| methods". I use both OOP and template based polymorphism
| depending on particular needs and see no significant
| problems in either.
| jhgb wrote:
| C++ can't do things today that Smalltalk and CLOS were
| able to do in the 1980s already; how is it _not_ lagging
| behind in OOP? Hell, companies like Trolltech had to
| extend C++ for their own purposes to provide just a
| subset of the extra features (relative to standard C++)
| that had already been available in environments like
| Smalltalk or CLOS.
| leni536 wrote:
| Sometimes (definitely not always) you can use
| std::function instead for dynamic polymorphism.
| jandrewrogers wrote:
| > very biased towards virtual methods
|
| This is a function of the type of software you write.
| There are many large C++ code bases that rely on various
| types of static polymorphism almost exclusively, rarely
| having a use case for virtual methods or dynamic
| polymorphism. There is a similar story with inheritance
| versus composition; some types of code bases naturally
| gravitate toward one or the other.
|
| The nice thing about C++ is that it as amenable to any of
| these models should it benefit the application.
| strictfp wrote:
| I don't agree. The support for static polymorphism is in
| it's infancy at best.
| jandrewrogers wrote:
| Can you give some examples of what you mean? I use static
| polymorphism in C++ routinely and haven't felt
| particularly limited by it.
| ryl00 wrote:
| > Creating trees or graphs can be cumbersome
|
| Wouldn't Rust have the same problem with this (if not
| worse)?
| jhgb wrote:
| I was told that deferred_ptr/deferred_heap was supposed
| to solve these things for C++, so perhaps that would make
| Rust the option with worse problems in this department.
| Not sure where it got by now, though.
| lmm wrote:
| > The issues that Rust is supposed to help with are simply
| not what we spent time on. All the bugs reported are pretty
| much exclusively root caused to "business logic".
|
| Everyone claims this, probably because business logic bugs
| are more memorable. But I've never seen it match the real
| statistics. According to the best published data, null
| alone is something like 30-70% of bugs, you just don't
| remember them because they're uninteresting.
| Macha wrote:
| It depends on the person's mental categorisation of bugs
| too. For example I could see someone classifying null
| bugs as business logic bugs because "the business logic
| didn't account for that information not always being
| there"
| jhgb wrote:
| It's a language bug, really. If you're _expected_ to say
| what the individual things in your program are allowed to
| be (like you have to in C++, Java, C# etc.), and you say
| "foo is a BarBaz object", and the language and compiler
| allow you to set foo to something that isn't actually a
| BarBaz object and this is considered OK, then the
| language is botched.
| capitainenemo wrote:
| I wonder if passing NaN is considered "business logic"
| Thinking of this interesting exchange long ago by an
| experienced c++ dev
|
| https://old.reddit.com/r/rust/comments/78bowa/hey_this_is
| _ky...
| staticassertion wrote:
| Unsurprisingly the types of bugs reported are going to be
| around business logic errors and not obscure edge case that
| users won't run into naturally. The bugs are still there
| though.
| hgomersall wrote:
| Right, and if you come across it you can't always
| reproduce it. "Oh it crashed, yeah it does that
| sometimes".
| xyzzy123 wrote:
| I think this mirrors my day to day experience with C++.
|
| On the other hand, fuzzing large c++ programs will
| routinely uncover memory safety issues in practically any
| large codebase that hasn't been absolutely beaten to death
| by fuzzers already.
|
| The issues are not usually so much "I returned this thing
| on the stack" they tend to be things like "this (very
| unexpected) sequence of api calls will result in a UAF in
| this deeply nested data structure over here on the heap".
| mwcampbell wrote:
| Counterpoint: When I was on the Windows accessibility team
| at Microsoft, one of my most brilliant colleagues gave a
| presentation about what to look for when doing code
| reviews, and he emphasized three main categories: C++, COM
| (Microsoft's Component Object Model), and concurrency. Rust
| eliminates many of the issues in the first and third
| categories. And yes, we were writing modern C++ as much as
| we could in that legacy codebase; by 2019 we were using
| several C++17 features, as well as the latest C++ utility
| libraries for working with COM and WinRT. Given the state
| of the Rust windows crate, that team (which both I and that
| colleague left in late 2020) might even be able to use Rust
| in new code. I'm sure that would make him happy.
| hinkley wrote:
| The exhausting part for me was always when the bug escapes
| detection for a little while, is associated with some new
| functionality that very much did _not_ escape detection, and
| it turns out that the wrong implementation is faster than
| possible. Now to fix the bug I get to be the bad guy and take
| away the customers toys (one of many many reasons to push for
| making the culprit fix the problem, especially if they don 't
| want to).
|
| It doesn't take many of these to form a coping mechanism that
| prevents this from happening again, even if it's at great
| cost. This is also the genesis of many unwinnable arguments
| that drag on forever.
| blub wrote:
| I find neither C++ nor Rust to be particularly "creative"
| programming languages because one has to think all the time
| about two things which are irrelevant for the features of the
| program - resource management and complicated types.
|
| Rust is even worse than C++ because it highly encourages
| encoding logic in types and the community loves doing that.
|
| You seem to have almost come to the same conclusion yourself,
| but then mistakenly assume that the same kind of productivity
| of a GC language is available in a system language. Nope.
| Although at least in C++ one can just say "fuck it" during
| the "creative" prototyping phase, copy most things and still
| have decent syntax and performance. In Rust you'd have to
| pepper everything with clone, boxes and (a)rc, so you'd have
| another mess.
| flohofwoe wrote:
| Static analyzers can catch this stuff nowaways (in this case
| clang's builtin analyzer):
|
| https://godbolt.org/z/1MfErrYd8
|
| ...in more simple cases it's also a regular warning:
|
| https://godbolt.org/z/5v9YsWd4j
| kevincox wrote:
| > less time debugging
|
| I would say it isn't even the debugging. As many of the C++
| programmers here have said as you get good at C++ this
| becomes something that you are vigilant for and it rarely
| actually gets written. But just the lack of even needing to
| think about it is a huge load off my mind. When I used to
| write C++ I never really realized how vigilant I was. Every
| time I added code into the middle of a function I had to
| double check all of the lifetimes, every time I shorted the
| lifetime of a variable I had to search for it to the end of
| the function. Just not having to worry about this much really
| frees your mind for thinking about other things.
| blub wrote:
| And what are you thinking about now?
|
| For me it was what lifetimes and types to use to make my
| program work. Just as it was in C++, but with a static
| verification step at the end which most of the time got in
| my way.
|
| Rust makes lots of sense in high-churn projects or projects
| which have very high security requirements (like browsers).
| Otherwise I'd think carefully about using it.
| fleventynine wrote:
| Reviewing commits for a security-critical project written in C
| or C++ can be incredibly tedious. I've spent an entire day
| trying to validate that the assumptions made by a 10-line
| change are memory-safe in the context of the larger program.
| These reviews are incredibly mentally draining, and even when
| I'm done I'm not 100% sure that I didn't miss something and let
| a vulnerability into the codebase.
|
| Rust is a breath of fresh air in comparison. Worrying about
| memory safety isn't even a concern for the vast majority of
| commits that don't touch modules with unsafe code. All
| assumptions made about the lifetimes of references are made
| explicit in the code, and checked by the compiler. On rust
| projects I find I have much more mental energy to use against
| other aspects of the problem.
| zh3 wrote:
| As someone considering learning Rust, the article put me off
| fast with the long preamble to even explaining what the issue
| was. I really hope it's not that complicated, but even your
| rebuttal fills me with fear - "corrupted data [......] being
| modified by unrelated operations on stack". How would you
| explain that to put a C programmers mind at ease?
| dj_mc_merlin wrote:
| If only his webserver were written in Rust.
| FpUser wrote:
| So many words to describe a simple issue of using reference to
| out of scope data. Anyways I am using C++ a lot and this types of
| bugs are easily caught by analyzers or straight up by modern IDEs
| like CLion (you get a warning).
| z3t4 wrote:
| A garbage collector has saved my brain from overfrying many
| times.
| munchler wrote:
| From the article: It's pointing out that we are
| pushing into this vector which needs references into "the
| AST", but we haven't declared in our signature that the
| ast::Ty must actually from "the AST".
|
| I think someone needs to write a typechecker for English to help
| out the author of this sentence.
| Linda703 wrote:
| labrador wrote:
| I've used Rust and I like it alright but it has the ugliest
| syntax of any major language since Perl
| proto_lambda wrote:
| Have you seen modern C++? It has had new syntax bolted on every
| couple years for the past few decades, the result is quite
| phenomenal.
| MauranKilom wrote:
| Can you name what new syntax you abhor?
|
| I mean, other than []<>(){}() being a valid C++ expression
| [0], C++ hasn't even made any notable sygil-related syntax
| changes recently. Sure, some keywords were added (auto,
| constexpr, co_yield...) but I don't see how that leads to
| "ugly" syntax.
|
| [0]: That's a lambda capturing no state, having no template
| parameters, taking no arguments, with an empty body, finally
| being called immediately with no arguments. But half of that
| is optional. A more usual lambda would look like [foo](int
| bar) { return foo+bar; }.
| kingaillas wrote:
| Anything with templates, type traits, especially when
| nested. (The kind of spew you get on an compilation error).
| Even template< typename T > struct
| foo<T, std::void_t<decltype(++std::declval<T&>() )>>
| : std::true_type { };
|
| looks terrible and that's just basic.
| masklinn wrote:
| I still wish Rust had a way to express decltype tho.
| `impl Trait` doesn't always work, and when it doesn't
| it's quite frustrating.
| estebank wrote:
| What limitation do you encounter with `impl Trait`? They
| might be removed by `type Alias = impl Trait;` soon.
|
| https://rust-
| lang.github.io/rfcs/2515-type_alias_impl_trait....
| marcosdumay wrote:
| You will notice that this is almost valid Rust. (Rust is
| a very small bit better, not enough to matter.)
|
| In fact, a lot of what the Rust syntax ugly was taken
| from C++, and it took most of what makes C++ ugly. So the
| entire discussion is just amusing.
| woodruffw wrote:
| I find the new user-defined literals syntax pretty ugly.
| Useful, but ugly.
|
| On the older side: the initialization list syntax has
| always been ugly (and bug-prone, due to the unintuitive
| evaluation order.)
| mkl wrote:
| Technically auto was already a keyword (from C) and was
| just repurposed. Pedantic but interesting.
| https://en.cppreference.com/w/c/keyword
| ImprobableTruth wrote:
| 'requires requires' makes me cry
| pclmulqdq wrote:
| Modern C++ looks horrendously ugly if you are a library
| writer, but on business logic it looks a lot tamer than rust.
| voidhorse wrote:
| agreed, I've tried to pick up rust a few times and the syntax
| has always made me give up halfway through the point of writing
| a real project. It's really a shame since they had every
| opportunity _not_ to make the syntax horrible. CPP has
| horrendous syntax but a lot of that is because they needed to
| start representing features over time that didn't exist from
| the ground up. Rust had pretty much all of its killer features
| form the start but for unknown reasons elected to use a
| tremendously noisy syntax that seems to be inspired by the
| monstrosity that is modern cpp syntax.
| kibwen wrote:
| It shouldn't be surprising that Rust's syntax is inspired by
| C++, Rust is literally designed to entice C++ programmers,
| and the syntax reflects that (modulo a handful of
| irresistible ML-isms to match the type system).
| ajdude wrote:
| This is my trouble with Rust. Thankfully Ada will do the same
| things addressed in this article while having a much more
| readable syntax.
| PointyFluff wrote:
| If only rust caught blogging security errors.
|
| It's a terrible idea to post a photo of your child with her name
| on your public blog.
|
| It's one of those subtle security things that the rust compiler
| helps with; but not here, sadly.
| rob74 wrote:
| Yes... but before you start feeling too sure about Rust
| protecting you from creating bugs, also consider this more
| cautionary (and very entertaining) tale posted on HN today:
| https://hacks.mozilla.org/2022/06/fuzzing-rust-minidump-for-...
| rq1 wrote:
| Well you'd have these bugs, plus the memory bugs in other
| languages.
| fnord123 wrote:
| They already did. Hence the rewrite from C++ to Rust.
| proto_lambda wrote:
| You mean the tale of someone rewriting a very complex and
| fiddly software from scratch, having it work great in
| production, and then using the ecosystem's great tooling to
| easily find and eliminate even more bugs than what the language
| already protected them from?
| kjksf wrote:
| The thing they rewrote also worked great in production.
|
| And fuzzing originated in C / C++ tools and is available for
| them as well, probably more diverse and mature than what is
| available in Rust.
|
| The point you did ignore was: Rust is being sold as magically
| making software safe and people selling that completely
| ignore the fact that logical bugs are also a thing.
|
| Which Rust evangelists find difficult to acknowledge because
| security is that one thing that Rust has going for it.
|
| So difficult that you would rather try to misdirect than to
| acknowledge that software written in Rust will crash. And
| when processing arbitrary user output, it'll crash badly when
| not written with care and fuzzed a lot. Kind of like C++.
| imron wrote:
| > The thing they rewrote also worked great in production.
|
| It may well have, but the Rust version "was faster, it
| crashed less, and we even knew it fixed some issues"
|
| https://hacks.mozilla.org/2022/06/everything-is-broken-
| shipp...
| kelnos wrote:
| > _Rust is being sold as magically making software safe and
| people selling that completely ignore the fact that logical
| bugs are also a thing._
|
| I don't think that's true. Sure, there are zealots who
| oversell things, but reasonable people (including those who
| are actual leaders in the Rust community) are realistic
| about the classes of bugs that Rust eliminates, as well as
| those Rust doesn't help with.
| sgift wrote:
| > The point you did ignore was: Rust is being sold as
| magically making software safe and people selling that
| completely ignore the fact that logical bugs are also a
| thing.
|
| There are straw men and then there are straw man armies.
| This is probably the biggest one I've seen yet.
| sitkack wrote:
| Ohh, I got one. Rust is _less_ secure than C++ because it
| causes people to be overconfident in its security
| properties. The sharp edges of C++ are a feature that
| cause people to focus on correctness, not just get it for
| free.
| [deleted]
| Thiez wrote:
| You jest, but that used to be an argument against making
| seatbelts mandatory in cars. I suppose people would drive
| even more safely if there was a sharp metal spike
| sticking out of the center of the steering wheel.
| kelnos wrote:
| Hell, this is a _current_ argument some people have
| against wearing bicycle and motorcycle helmets.
| Thiez wrote:
| Is it? For bicycle helmets I just know these variants:
|
| 1. Wearing a bicycle helmet is unpleasant, so people will
| cycle less and possibly use other modes of transportation
| such as cars. The risk of a traumatic head injury may
| decrease but this is offset either partially or fully by
| other health risks such as obesity.
|
| 2. _Other_ road users in heavier vehicles (e.g. cars)
| perceive riders wearing bicycle helmets as less
| vulnerable, and so keep less distance when overtaking
| them, thus wearing a helmet increases the risk of
| collision.
|
| I don't think I've ever heard someone say they won't wear
| a bicycle helmet because it would make them personally
| drive more dangerously.
|
| I personally strongly oppose mandatory bike helmets. I
| think one of the reasons so many people own and ride
| bikes in my country (The Netherlands) is that we don't
| have mandatory helmets. Making helmets mandatory for
| people inside cars would also prevent or reduce head
| injuries (and indeed that is why they are worn by race
| car drivers) so if we ever introduce mandatory bicycle
| helmets here perhaps we can introduce mandatory car
| helmets at the same time, to ensure that people won't
| just take a car instead.
| sitkack wrote:
| This assumes that each person is responsible for their
| own safety. But you have no control over the other guy
| that puts people at risk. By mocking it, maybe we can
| prevent this form of argumentation earlier?
|
| Hopefully in 20 years or less we will see unsafe code in
| the same way we view leaded gas, cigarettes and CO2. The
| other thing I realized in the last couple years is that
| eventually, everything becomes safety critical to someone
| at some point. That if you think you have to _just_
| protect this one system but that others can fail, is
| flawed on large scales. You can 't tractably realize the
| failure graph, and nor can you prevent a seemingly
| innocuous thing from being used in a critical way.
|
| The pandemic was a great lens into how human resilience
| kept flawed systems functioning in a way that few
| realized were flawed. The pharmacies in my area are still
| recovering only to have their problem exacerbated by more
| rigid controls that prevent local autonomy from making
| the system resilient. In this particular case, automation
| has made a problem worse by preventing humans from doing
| the little local silent repairs that they were previously
| doing.
| carrionpigeon wrote:
| The great (unintentional?) irony of that argument is that
| before seatbelts, that was arguably how cars used to be
| manufactured. Back then, drivers were often killed in car
| crashes by being impaled on the steering wheel. Those in
| the passenger seat would die from being hurled through
| the window. Despite the elevated risk in those older
| cars, drivers weren't safer --- they were unsafe to such
| a degree that it formed the argument for mandating seat
| belts in the first place.
| proto_lambda wrote:
| > The thing they rewrote also worked great in production.
|
| It didn't for them, that's why they rewrote it.
|
| > Rust is being sold as magically making software safe and
| people selling that completely ignore the fact that logical
| bugs are also a thing.
|
| By whom? I don't think memory safety bugs are the only
| class of bugs, and neither do you, so who are you arguing
| against?
|
| > Which Rust evangelists find difficult to acknowledge
| because security is that one thing that Rust has going for
| it.
|
| Hard disagree. Rust also offers a solid type system, pain-
| free dependency management and all-around good tooling,
| just to name a few. It's much more than a "memory-safe C++"
| or whatever.
|
| > And when processing arbitrary user output, it'll crash
| badly
|
| If your definition of "badly" is "at a well-defined point,
| without any memory corruption", sure. But even here memory
| safety prevents what could be a much more painful debugging
| experience.
| ordu wrote:
| _> The point you did ignore was: Rust is being sold as
| magically making software safe and people selling that
| completely ignore the fact that logical bugs are also a
| thing._
|
| You know, I'm a Rust evangelist. And I can tell you, why I
| ignore logic bugs when trying to sell Rust. Rust can
| prevent some logic bugs if they break invariant you managed
| to encode or enforce in your types. But it is a difficult
| topic to dive in a internet discussion. The best I could do
| is to bring some anecdotal data points, like &str being
| guaranteed to contain only valid utf8 strings. The worse
| issue (for a discussion) that it may be not obvious what
| kind of a logic error can be fixed by the type invariant
| discussed. So to show it I need to find some more examples
| of bugs that were prevented by enforcing the invariant. But
| you see, bugs that were prevented were not documented. It
| goes like this: you write code, it doesn't compile because
| rustc is unhappy, you fix code and it compiles nice now,
| you call it a day and move along. When you fixed this small
| issue it was not a bug, just one of a several complaints of
| rustc. You would need to speculate a lot about what could
| happen bad if rust allowed this issue to live.
|
| We can try to get to the point from a different angle and
| to find logic errors in a wild, and then to speculate how
| type invariants might prevented them _if programmers had
| written their types in a some particular way_. But it raise
| a question: would they write their types in this way before
| they faced this particular logic error?
|
| If I tried to talk about complex relationships of Rust and
| logic errors, I would need to dive into an ocean of
| speculations. Rust deniers are not very cooperative on this
| regard, and I'd bet they would just dismiss all the
| speculations as... well... speculations. And they would
| keep insist that if we cannot measure a falling frequency
| of logic bugs, then it is all immaterial. Some even go
| further and claim that if some tool doesn't prevent _all_
| bugs of a kind, then it is a useless thing.
|
| So it is not a fun to talk about logic errors with rust
| deniers. Among rust evangelists the talk doesn't happen
| either, because they do not split bugs into two categories
| "logic" and "memory" bugs, they split them into "can be
| prevented by type invariant" and "cannot be prevented by
| type invariant, or too f*king difficult to". They talk
| about memory safety to laymen because it is something that
| laymen understand and it doesn't need explaining. And Rust
| can prevent all the bugs of this kind, so even when we talk
| to a people who thinks in black-and-white, we can make
| statements that are defensible in this Aristotelian
| tradition of excluded middle.
| sitkack wrote:
| You often encounter this entire thread of rhetoric when
| someone wants to put a diversion into the central
| argument, yeah but it doesn't ____.
|
| But Rust _does_ do that, match exhaustiveness, forcing
| the handling of errors and the type system enables things
| like CreuSAT [1] using creusot [2]
|
| [1] https://news.ycombinator.com/item?id=31780128
|
| [2] https://github.com/xldenis/creusot
|
| > Creusot works by translating Rust code to WhyML, the
| verification and specification language of Why3. Users
| can then leverage the full power of Why3 to
| (semi)-automatically discharge the verification
| conditions!
|
| Units of Measure, https://github.com/iliekturtles/uom
|
| The base properties of the language enable things that
| can _never_ be done in C++.
| scatters wrote:
| You mean like Boost.Units?
| sitkack wrote:
| Great example of the kind of cherry picking in these
| conversations. It is insincere and uncharitable, all you
| did was show your colors. Didn't say everything was
| exclusive to Rust, while you make no mention on the
| ground breaking work in CreuSAT. Given as an example of
| the kinds of things besides memory lifetime tracking that
| can make Rust code more robust against logical errors.
| rob74 wrote:
| What you said, although I would have probably phrased it
| less harshly :)
|
| But yes, my point was that there are a lot of enthusiastic
| articles about how Rust can prevent "whole classes of
| bugs", which mostly gloss over the fact that there are
| other classes of bugs that it doesn't prevent. Of course
| this doesn't mislead experienced developers, but I'm not so
| sure about novices or less technically inclined people.
| nindalf wrote:
| It seems like it is true and accurate to say that Rust
| prevents "whole classes of bugs". It is obvious that
| other bugs can still exist. Otherwise people would say
| Rust prevents "all bugs".
|
| Are you disappointed that Rust evangelists don't spend
| time talking about the fact that bugs can exist in Rust
| programs? Did you see the two articles posted in the last
| week alone about bugs that were found in Rust code? They
| reached the front page of HN
|
| - https://hacks.mozilla.org/2022/06/everything-is-broken-
| shipp...
|
| - https://hacks.mozilla.org/2022/06/fuzzing-rust-
| minidump-for-...
|
| If you want to see criticism of Rust, I've found that the
| most informed criticism comes from people who use Rust a
| lot. Example - https://matklad.github.io/2020/09/20/why-
| not-rust.html
| tremon wrote:
| _which mostly gloss over the fact that there are other
| classes of bugs that it doesn 't prevent_
|
| That's nothing more than a technically-dressed version of
| whataboutism, isn't it? Or can you show other languages
| that _do_ prevent those other unnamed classes of bugs?
| rob74 wrote:
| Er... no. I was simply saying that the many articles
| about how reliable Rust is and how many bugs it catches
| for you might lead to a false sense of safety. Nothing
| more, nothing less.
| supportlocal4h wrote:
| What's the use of standing on that anti-static mat and
| wearing that grounding strap? Can't you see there are
| fork lifts zipping around just right in the next room?
| That mat is giving you a false sense of security!
| carnitine wrote:
| This seems like the opposite of a cautionary tale, if anything
| it makes Rust seem an even better choice.
| ekidd wrote:
| I have run "cargo fuzz" (based on the AFL fuzzer) over a
| binary-format parsing library I wrote, generating roughly a
| billion inputs. Here's what I learned:
|
| 1. Rust does not protect you at _compile time_ against "index
| out of bounds" errors. If you want that, you'll want a
| dependently-typed language like Idris. Which still wouldn't
| help much in this case.
|
| 2. However, Rust catches index errors perfectly well at
| _runtime,_ and performs a controlled panic. This does not
| result in a privilege escalation, but it may cause a denial of
| service. So fuzzing in (safe) Rust is normally a "lower
| stakes" activity.
|
| 3. "cargo fuzz" is super easy to use, and AFL is pretty
| amazing.
|
| 4. If you think you can parse complex, badly-documented low-
| level binary formats without ever having an index error, you're
| probably wildly overconfident. In the case of the minidump
| parser, it's worse: The data was generated by a crashing
| process, and in many cases, the data _caused_ the crash.
|
| Let's look at what the author concludes:
|
| > _And what did we screw up? Some legit stuff! It's Rust code,
| so I am fairly confident none of the issues were security
| concerns, but they were definitely quality of implementation
| issues, and could have been used to at very least denial-of-
| service the minidump processor._
|
| A whole bunch of issues, probably none of them leading to
| security escalations. And unlike many C fuzzing experiences, it
| was largely painless:
|
| > _By comparison I am absolutely thriving under "Yeah you can
| deterministically trip this assertion with this tiny input you
| can just check in as a unit test"._
|
| This happens because Rust catches most of these errors very
| early, using assertions in the standard library. So your fuzz
| reports often need to be tracked for only a few lines.
|
| TL;Dr: Parsing complex binary formats usually involves subtle
| bugs. Rust does not promise to catch index-out-of-bounds at
| compile-time, but it catches them at runtime. This makes
| fuzzing easy and productive.
|
| Overall, I'd call this a success story. The author underwent an
| inevitably humbling experience for low stakes under controlled
| conditions. And now the library can parse corrupted examples of
| an incredibly nasty format, with high confidence that the worst
| thing that will happen is a runtime error (not even a DoS).
| hnarn wrote:
| > I needed a bit of palette cleanser
|
| This is a fun mistake. It's "Palate cleanser".
| rob74 wrote:
| Works with palette (as in painter's palette) too - start with
| a clean slate, use a whole different set of colors etc.
| gpderetta wrote:
| Maybe they just want to drink solvent. A common reaction
| after dealing with very bad code for a while.
| inox wrote:
| I was looking for some kind of story related to cooking bacon
| with Rust -> disappointed. Bacon is only used once - in the
| heading...
| proto_lambda wrote:
| It's an idiom:
| https://en.wiktionary.org/wiki/save_someone%27s_bacon
| antegamisou wrote:
| Similarly expected a firmware write-up for an IoT BBQ.
| axilmar wrote:
| Rust is undoubtedly a step forward in correctness, but boy, the
| article's code is so thick that for me, that I am a C++
| programmer, is almost unreadable, especially for a quick
| reading...
|
| I skipped all the code and only read the text. I got to the point
| where it mentions that the language prevented them from storing a
| pointer to a stack object in a heap object, and that's really
| great, but boy oh boy, the code presented, and the error
| messages, where very difficult for me to grok even after the
| first few times...
|
| It seems to me that the more sophisticated the safety a language
| provides is the more complex its error messages/code are. It
| would be so nice if we could solve both problems at the same
| time...
| dijit wrote:
| For whatever it's worth: I think it's harder to learn rust as a
| C++ programmer than it is for a new programmer.
|
| Reason being that you have to unlearn your paradigm before
| you're able to learn the new paradigm; and it's made slightly
| worse by giving the appearance of similarity (since certain
| concepts map directly, like flow control and loops).
| proto_lambda wrote:
| One big hurdle for C++ programmers learning Rust that I've
| seen time and time again in various community support
| channels is fixing their trust issues with the compiler. They
| are so used to compiler output being useless or worse than
| useless, they are unable to take advantage of rustc's stellar
| diagnostics (which frequently tell you exactly what you need
| to change to make things work) until they force themselves to
| actually read and internalise them.
|
| Once they realize that the tooling is actually working _with_
| them, not _against_ them, they start to pick things up much
| quicker.
| lionkor wrote:
| In my experience only beginners have this issue, as a C++
| programmer the compiler is my best friend.
| scoutt wrote:
| > big hurdle
|
| Without going much further, to me it's the syntax. I can
| write some Rust lines of code, and I appreciate the
| compiler output to correct my syntax. But it's really
| difficult to me to read code written by others. I can't
| open a random file of a Rust project and have a minimal
| clue of what's going on
|
| After years of C and some C++, I have a parser implanted in
| my cerebellum, and it's hard to adapt it to Rust. To me,
| reading Rust feels like forcing an optical nerve to see
| something very small.
|
| Case in point, the code in this article.
| bilkow wrote:
| Oh yeah, I feel your pain, my brain is really used to
| Rust/Swift and Python syntax, and when I have to read
| Typescript/React, C++ or something like Nix, it gets hard
| for my brain to parse it. Loved the eyesight analogy!
| lawn wrote:
| As a Rust programmer I think the code could have been made much
| simpler and still get the point across.
|
| I think the author wanted to replicate the code as closely as
| possible, so it's more a case study than an educational piece
| if that makes sense?
| dgb23 wrote:
| I skimmed the code and there are a ton of language features in
| there that you might not be super familiar with:
|
| - pattern matching is quite expressive and ubiquitous in Rust,
| as in "stuff on the left" is almost always a pattern even in
| places that you might not expect at first
|
| - lifetime annotations, a form of generics, are quite unique
| and make the code more verbose/noisy if you are not familiar
| with them
|
| - Rust is expression based (a bit lispy) so you might not quite
| see the flow of the program as well if you are used to
| statement based syntax
|
| - traits are are an important part of the language and some of
| the methods and method chains you see there might look
| arbitrary, but many of them are very common. A more experienced
| reader can identify many of them and see the code very
| differently.
|
| - there is no syntax highlighting on the article's snippets so
| you already have to know how to parse them
| azakai wrote:
| > It seems to me that the more sophisticated the safety a
| language provides is the more complex its error messages/code
| are. It would be so nice if we could solve both problems at the
| same time...
|
| That is incredibly hard, yes. But at least if you are ok with
| the overhead of GC or RC then this is a solved problem - the
| bug in question here wouldn't happen in
| Go/Swift/C#/Java/JavaScript/Python/Ruby/etc. And that is most
| software today.
|
| (But when you need maximal performance and maximal safety then
| Rust is an incredible option!)
| OneWingedShark wrote:
| Look at Ada and its error-messages.
| blub wrote:
| After reading a good chunk of the Programming Rust book (minus
| concurrency, async and macros) I can understand that. My C++
| experience helped a lot in comprehending and mentally mapping
| Rust concepts.
|
| As far as I can tell, that's normal Rust code, but yes it's
| unreadable if you come from C++ or another language and don't
| know Rust syntax. The funny thing is that this kind of code is
| supposed to be the readable part of Rust :-)
___________________________________________________________________
(page generated 2022-06-24 23:03 UTC)