HNHacker News
TopNewBestAskShowJobs

timhh

814 karma · joined December 24, 2017

submissionscomments
timhh··on NASA announces overhaul of Artemis program amid safety concerns, delays
> the capabilities are so far mostly just talk

lol what? They've caught and successfully reflown the super heavy booster, and they've mostly successfully done a soft landing of Starship in the sea. How is that remotely "just talk"?

timhh··on Sudo-rs enables pwfeedback by default for Resolute Raccoon
I recently started using Linux again, and decided to try and fix some of its more ancient and silly UX paper cuts. This is my first success!

My attempt to fix the annoying and unnecessary 2 second delay when you mistype your password is going rather less well: https://github.com/linux-pam/linux-pam/pull/789

Does anyone want to rewrite PAM in Rust? :D

timhh··on RISC-V Vector Primer
If you get lost in the SEW, LMUL, VLMAX, etc. stuff I made a brief explanation here:

https://blog.timhutt.co.uk/riscv-vector/

It has a visualisation of the element selection stuff at the end.

timhh··on Prek: A better, faster, drop-in pre-commit replacement, engineered in Rust
It's going to be optional - the hooks will always fix the code if they can, but then you can supply a `--no-fix` flag (or config) if you want to tell it to not actually apply those changes to the real filesystem.

It doesn't need Landlock because WASI already provides a VFS.

timhh··on Prek: A better, faster, drop-in pre-commit replacement, engineered in Rust
It is better because of WASI. That's what provides sandboxing.
timhh··on Arcan-A12: Weaving a Different Web
> just a little to different and obscure

Even the style of writing screams "I'm doing something weird and I'm not going to explain it to you unless you are already a mega-fan". Reminds me of Wolfram's writing a bit. He's created a world that only he is in and then writes about it in detail as if everyone else is there too.

timhh··on The Codex app illustrates the shift left of IDEs and coding GUIs
Not really what "shift left" means...
timhh··on Voxtral Transcribe 2
You could say the same about Dutch to be fair. 90-95% speak English - I bet that's way higher than in Poland.
timhh··on Voxtral Transcribe 2
Yeah it messed up a bit for me too when I didn't enunciate well. If I speak clearly it seems to work very well even with background noise. Remember Dragon Naturally Speaking? Imagine having this back then!
timhh··on Prek: A better, faster, drop-in pre-commit replacement, engineered in Rust
> the second the hooks modify the code they've broken your sandbox

Changes to code would obviously need to be reviewed before they are committed. That's still much better than with pre-commit, where e.g. to do simple things like banning tabs you pretty much give some guy you don't know full access to your machine. Even worse - almost everyone that uses pre-commit also uses tags instead of commit hashes so the hook can be modified retroactively.

One interesting attack would be for a hook to modify e.g. `.vscode/settings.json`... I should probably make the default config exclude those files. Is that what you meant? Even without that it's a lot more secure than pre-commit.

timhh··on Prek: A better, faster, drop-in pre-commit replacement, engineered in Rust
I have also been working on an alternative written in Rust, but in my version the hooks are WASI programs. They run on a virtual filesystem backed by the Git repo. That means a) there are no security issues (they have no network access, and no file access outside the repo), b) you can run them in parallel, c) you can choose whether to apply fixes or not without needing explicit support from the plugin, and most importantly d) they work reliably.

I'm sure this is more reliably than pre-commit, but you still have hooks building Python wheels and whatnot, which fails annoyingly often.

https://github.com/timmmm/nit

The VFS stuff is not quite finished yet though (it's really complicated). If anyone wants to help me with that it would be welcome!

timhh··on Yep, Passkeys Still Have Problems
TOTP is really annoying IMO but at least you control it so you can make it one-factor again if it's foisted on you. I made a Chrome extension to do that:

https://chromewebstore.google.com/detail/lazyotp/eoihmklnjkn...

timhh··on Homebrew on Linux
The absolute prefix requirements (similar to Nix, and I guess for the same reason) mean this probably can't be used where it would be most useful - on machines that you don't control.

I wonder if anyone will ever make something like this but where all the software has to be relocatable (no hard-coded absolute paths).

I guess a lot of software would be excluded or need patching, but I think it would be useful and maybe it would encourage Linux developers to stop bloody hard-coding absolute paths like it's still the 90s!

timhh··on Building road signs at home using a Cricut Machine
There's also this thing that I wrote. I've been meaning to update it for a long time but life...

http://robocut.org/

timhh··on Why I love OCaml (2023)
> Crates.io is an unmoderated wasteland of infinite transitive dependency chaos

Well, I'm not sure I agree with that. If by "unmoderated" you mean anyone can upload a crate without going through bureaucratic approvals processes then that seems like a good thing to me!

But you did remind me of one other majorly annoying thing about the crate system: the global namespace. It doesn't have the same security issues as Python's global package namespace, but it is really really annoying because you pretty much have to break large projects down into multiple crates for compile time reasons, and then good luck publishing those on crates.io. Plus you end up with a load of crate names like `myproject-foo`, `myproject-bar`, which is very verbose.

Oh and yeah, the Tokio situation is a bit sad.

Also the proliferation of some types of crates like error handling. This should really be in the standard library by now (or at least fairly soon). Any large project ends up with like 5 different error handling libraries just because dependencies made different choices about which to use. It's not a major issue but it is silly.

Overall though, still my favourite language by far.

timhh··on Why I love OCaml (2023)
I don't think you would be flagged. Rust definitely has flaws:

* Compile time is only ok. On par with C++.

* Async has a surprisingly number of footguns and ergonomic issues.

* There's no good solution to self-borrowing or partial borrows.

* While using macros is fine, writing them is pretty awful. Fortunately you rarely need to do that. Relatedly it is missing introspection support.

* Sometimes the types and lifetimes get very complex.

But overall I still much prefer it to OCaml. The syntax is much nicer, it's easier to read, the ecosystem and tooling are much better, the documentation is much better, and it actively hates linked lists!

timhh··on Why I love OCaml (2023)
> why isn’t OCaml more popular

I've used OCaml a bit and found various issues with it:

* Terrible Windows support. With OCaml 5 it's upgraded to "pretty bad".

* The syntax is hard to parse for humans. Often it turns into a word soup, without any helpful punctuation to tell you what things are. It's like reading a book with no paragraphs, capitalisation or punctuation.

* The syntax isn't recoverable. Sometimes you can add a single character and the error message is essentially "syntax error in these 1000 lines".

* Ocamlfmt is pretty bad. It thinks it is writing prose. It will even put complex `match`es on one line if they fit. Really hurts readability.

* The documentation is super terse. Very few examples.

* OPAM. In theory... I feel like it should be great. But in practice I find it to be incomprehensible, full of surprising behaviours, and also surprisingly buggy. I still can't believe the bug where it can't find `curl` if you're in more than 32 Unix groups.

* Optional type annotation for function signatures throws away a significant benefit of static typing - documentation/understanding and nice error messages.

* Tiny ecosystem. Rust gets flak for its small standard library, but OCaml doesn't even have a built in function to copy files.

* Like all FP languages it has a weird obsession with singly linked lists, which are actually a pretty awful data structure.

It's not all bad though, and I'd definitely take it over C and Python. Definitely wouldn't pick it over Rust though, unless I was really worried about compile times.

timhh··on Writing a RISC-V Emulator in Rust
Those architectures are all much older than RISC-V from a time when it wasn't quite so blindingly obvious that Little Endian had won the debate.
timhh··on Writing a RISC-V Emulator in Rust
> So when a little-endian system needs to inspect or modify a network packet, it has to swap the big-endian values to little-endian and back, a process that can take as many as 10-20 instructions on a RISC-V target which doesn’t implement the Zbb extension.

See this justification doesn't make any sense to me. The motivation is that it makes high performance network routing faster, but only in situations where a) you don't implement Zbb (which is a real no-brainer extension to implement), and b) you don't do the packet processing in hardware.

I'm happy to be proven wrong but that sounds like an illogical design space. If you're willing to design a custom chip that supports big endian for your network appliance (because none of the COTS chips do) then why would you not be willing to add a custom peripheral or even custom instructions for packet processing?

Half the point of RISC-V is that it's customisable for niche applications, yet this one niche application somehow was allowed and now it forces all spec writers and reference model authors to think about how things will work with big endian. And it uses up 3 precious bits in mstatus.

I guess it maybe is too big of a breaking change to say "actually no" even if nobody has ever actually manufactured a big endian RISC-V chip, so I'm not super seriously suggesting it is removed.

Perhaps we can all take a solemn vow to never implement it and then it will be de facto removed.

timhh··on Writing a RISC-V Emulator in Rust
Python still doesn't do very well on backwards compatibility & bitrot, even after 3. They're constantly deprecating and removing things.

https://docs.python.org/3.12/deprecations/index.html

This obviously improves Python, but also it means you absolutely shouldn't choose Python if you are looking for a low maintenance language.

timhh··on Writing a RISC-V Emulator in Rust
> RISC-V has either little-endian or big-endian byte order.

Yeah though for instruction fetch it's always little endian. I honestly think they should remove support for big endian from the spec. As far as I know nobody has implemented it, the justification in the ISA manual is very dubious, and it adds unneeded complexity to the spec and to reference models.

Plus it's embarrassing (see Linus's rant which I fully agree with).

timhh··on Writing a RISC-V Emulator in Rust
I'm pretty sure Rust is going to outlast x86! C definitely will.
timhh··on Writing a RISC-V Emulator in Rust
I think assembly is probably a pretty bad choice for a RISC-V emulator. It's not portable, a nightmare to maintain, and not even as fast as binary translation.

What kind of performance do you get?

I guess it would be a great way to learn about the differences between x86 and RISC-V though!

timhh··on Why do browsers throttle JavaScript timers?
I think that change is talking about the minimum timeout for the first 5 nested calls to `setTimeout(0)`.

Previously the first 5 would take 1ms, and then the rest would take 4ms. After that change the first 5 take 0ms and the rest take 4ms.

timhh··on Why do browsers throttle JavaScript timers?
I asked about this a few years ago on SO and there is some good info: https://stackoverflow.com/q/61338780/265521

E.g. Chrome has this comment:

  // Chromium uses a minimum timer interval of 4ms. We'd like to go
  // lower; however, there are poorly coded websites out there which do
  // create CPU-spinning loops.  Using 4ms prevents the CPU from
  // spinning too busily and provides a balance between CPU spinning and
  // the smallest possible interval timer.
At the time at least the 4ms only kicks in after 5 levels of nesting, as mentioned in the article, but there was still a 1ms limit before that.

Seems like it has been removed though based on jayflux's comment.

timhh··on GTP Blind Voting: GPT-5 vs. 4o
I have a lot of experience with pairwise testing so I can explain this.

The reason there isn't an "equal" option is because it's impossible to calibrate. How close do the two options have to be before the average person considers them "equal"? You can't really say.

The other problem is when two things are very close, if you provide an "equal" option you lose the very slight preference information. One test I did was getting people to say which of two greyscale colours is lighter. With enough comparisons you can easily get the correct ordering even down to 8 bits (i.e. people can distinguish 0x808080 and 0x818181), but they really look the same if you just look at a pair of them (unless they are directly adjacent, which wasn't the case in my test).

The "polluted by randomness" issue isn't a problem with sufficient comparisons because you show the things in a random order so it eventually gets cancelled out. Imagine throwing a very slightly weighted coin; it's mostly random but with enough throws you can see the bias.

...

On the other hand, 16 comparisons isn't very many at all, and also I did implement an ad-hoc "they look the same" option for my tests and it did actually perform significantly better, even if it isn't quite as mathematically rigorous.

Also player skill ranking systems like Elo or TrueSkill have to deal with draws (in games that allow them), and really most of these ranking algorithms are totally ad-hoc anyway (e.g. why does Bradley-Terry use a sigmoid model?), so it's not really a big deal to add more ad-hocness into your model.

timhh··on The Sail instruction-set semantics specification language
Yeah you can describe basically any ISA including SIMD. The RISC-V model doesn't support packed SIMD (the P extension) but it does support Vector.
timhh··on The Sail instruction-set semantics specification language
It's still kind of experimental. Also the purpose is more for formal verification against a real design. The RISC-V model doesn't have any microarchitectural features you'd need for a real chip - not even pipelining - so it would be very slow.

Still... it is tantalisingly close to a really nice HDL for design purposes. I have considered trying to make a pipelined RISC-V chip in Sail with all the caches, branch predictor etc.

One feature that makes it a little awkward though is that there isn't really anything like a class or a SV module that you can reuse. If you want to have N of anything you pretty much have to copy & paste it N times.

timhh··on The Sail instruction-set semantics specification language
I've used this a lot via the RISC-V Sail model: https://github.com/riscv/sail-riscv

It's a really nice language - especially the lightweight dependent types. Basically it has dependent types for integers and bit-vector lengths so you can have some really nice guarantees. E.g. in this example https://github.com/Timmmm/sail_demo/blob/master/src/079_page... we have this function type

  val splitAccessWidths : forall 'w, 0 <= 'w . (xlenbits, int('w)) ->
    {'w0 'w1, 'w0 >= 0 & 'w1 >= 0 & 'w0 + 'w1 == 'w . (int('w0), int('w1))}
Which basically means it returns a tuple of 2 integers, and they must sum to the input integer. The type system knows this. Then when we do this:

  let (width0, width1) = splitAccessWidths(vaddr, width);
  let val0 = mem_read_contiguous(paddr0, width0);
  let val1 = mem_read_contiguous(paddr1, width1);
  val1 @ val0
The type system knows that `length(val0) + length(val1) == width`. When you concatenate them (@ is bit-vector concatenation; wouldn't have been my choice but it's heavily OCaml-inspired), the type system knows `length(val1 @ val0) == width`.

If you make a mistake and do `val1 @ val1` for example you'll get a type error.

A simpler example is https://github.com/Timmmm/sail_demo/blob/master/src/070_fanc...

The type `val count_ones : forall 'n, 'n >= 0. (bits('n)) -> range(0, 'n)` means that it's generic over any length of bit vector and the return type is an integer from 0 to the length of the bit vector.

I added it to Godbolt (slightly old version though) so you can try it out there.

It's not a general purpose language so it's really only useful for modelling hardware.

timhh··on Code Execution Through Email: How I Used Claude to Hack Itself
Yeah I also don't understand how this is unexpected. You gave Claude the ability to run arbitrary commands. It did that. It might unexpectedly run dangerous commands even if you don't connect it to malicious emails.
← PreviousPage 2 of 5Next →