HNHacker News
TopNewBestAskShowJobs

suyjuris

191 karma · joined April 8, 2019

https://nicze.de/philipp/

contact@nicze.de

submissionscomments
suyjuris··on Kids find a security flaw in Linux Mint by mashing keys
I have used AFL a few times casually in some personal projects, and it has always performed quite well for me. Of course, there are a lot of weird cornercases which would not occur on real-world (non-adversarial) inputs, but it also found some very real bugs.

(For example, I once wrote a hash table implementation where the insertion and resizing procedures had slightly different views on wraparound, causing failures on very specific inputs. Another time, I wrote some code to buffer out-of-order messages, which would only occur due to a race condition. It was wrong. Both times I had thought carefully about the code, and the bugs would have been painful to discover otherwise.)

suyjuris··on Test for Divisibility by 13
I never thought about that! That definitely is an interesting connection.
suyjuris··on Test for Divisibility by 13
Instead of remembering the weighted sequence, you can also compute it implicitly as you go (when reading the number from left to right). Example:

    8
    ^ 8 (mod 7) is 1, remember that
    85
     ^ 1 · 10 (mod 7) is 3, and 3 + 5 (mod 7) is 1, remember that
    853
      ^ 1 · 10 + 3 (mod 7) is 6
    8536
       ^ 6 · 10 + 6 (mod 7) is 3
    85362
        ^ 3 · 10 + 2 (mod 7) is 4
    853629
         ^ 4 · 10 + 9 (mod 7) is 0
Hence 853629 (mod 7) = 0 and it is divisible by 7. The corresponding code would be

    def modulo(number, k):
        val = 0;
        for digit in str(number):
            val = (val * 10 + int(digit)) % k
        return val
Of course, you can apply the modulo within the intermediate calculations as well, so instead of multiplying by 10 you can e.g. multiply by 3 = 10 (mod 7) instead. The key idea is that you can go from one weight to the next by multiplying with 10 (mod 7), so if you sum some weighted digits you can update all the weights at once with a simple multiplication.

The advantage is that you only need a small amount of memory (a single number between 0 and 6), so this is a kind of general divisibility rule where you only have to do small calculations in your head.

If I may digress a bit into automata theory, this means that you can construct a finite state automaton that determines whether a number is divisible by 7 (or any other constant) by reading its digits from left to right. Additionally, if a finite state automaton can do something reading from left to right, there is another automaton doing the same thing but reading from right to left. This means that there is also a 'simple' divisibility rule when starting with the least significant digit, though it may be a bit harder to find.

suyjuris··on Why I'm Tcl-Ish
The string command accepts a special syntax for indices, which includes addition (but not the full power of expr) [1]. Maybe you are referring to this? Also, list commands accept the same syntax for list indices.

Example:

    % string index abc 1
    b
    % string index abc 1+1
    c
    % string index abc 1+1+1
    bad index "1+1+1": must be integer?[+-]integer? or end?[+-]integer?
    % string index abc end-1
    b
[1] http://www.tcl.tk/man/tcl8.6/TclCmd/string.htm#M54
suyjuris··on Single_file_libs: List of single-file C/C++ libraries
I do the same thing, it works great!
suyjuris··on YouTube-dl has received a DMCA takedown from RIAA
That is not the argument, though. Your copyright is protected regardless of the strength of your security measures. But it is also, separately, illegal to circumvent these measures. This latter prohibition becomes more far-reaching and has more collateral damage the weaker the security measures it applies to, which is worrying.

Outlawing the methods of committing a crime also (instead of just the crime) requires a balancing act between their legitimate and illegitimate uses, which seems precariously absent when talking about technically laughable “security measures” that can be circumvented by pressing F12.

suyjuris··on Challenge to scientists: does your ten-year-old code still run?
I wrote a tool to visualise algorithms for binary decision diagrams [1], also in an academic context, where the problem was basically the same: Does the code still run in ten years? In particular, the assumption is that I will not be around then, and no one will have any amount of time to spend on maintenance.

In the end, I chose to write it in C++ with minimal dependencies (only X11, OpenGL and stb_truetype.h), with custom GUI, and packed all resources into a single executable.

A lot of effort, but if it causes the application to survive 5x as long then it is probably worth spending twice the time.

[1] https://github.com/suyjuris/obst

suyjuris··on Handmade: A Community for Self-Rolled Performant Software (2016)
What do you think about the following trade-off? (a) make a software accessible to 99.9% of the population with base-level quality-of-life (b) only be accessible to 98% but increase quality-of-life by 5% for the rest

(I am not trying to make a point, just curious.)

suyjuris··on Factorio 1.0
> Nuclear bombs can be used to one-shot endgame biter bases.

Forget biters, nuclear bombs quickly remove large numbers of trees, which are the true enemy!

On a more serious note, there have also been countless quality of life improvements, like high-resolution graphics, reworked UI, or copy-and-paste (literally just Ctrl-C / Ctrl-V, I have used it even without robots, its so convenient). If you have radar coverage, the map allows zooming in fully (rendered just like the normal view) and you can place blueprints and issue deletion commands anywhere on the map without moving.

Incidentally, you can also order artillery strikes to play a 'prank' on your unsuspecting friend who is standing motionlessly. (Which is why I made a habit out of standing close to the most expensive thing in the vicinity.)

suyjuris··on IBM completes successful field trials on Fully Homomorphic Encryption
Easy, just square it. Also, the Ackermann function is not a primitive recursive function.
suyjuris··on Typometer: A tool to measure and analyze the visual latency of text editors
> However, you're not feeling the latency. You're noticing the presence of two distinct signals.

Not necessarily; it could be an electronic instrument.

I once tested a "e-piano -> midi -> PC -> headphones" chain. The latency was not really noticeable when I pressed only a single key, but actually playing was impossible. After I replaced a (software) component with something with lower latency, it was bearable. While I cannot precisely estimate the latency reduction, I would guess that it was less than 30ms.

suyjuris··on Data structures and algorithms I actually used while working at tech companies
> I say it works better, because it has the same asymptotic runtime [...]

To be fair, while the asymptotic runtime may be the same, the C version is about 180 times faster.

suyjuris··on Data Definition and Code Generation in Tcl (2014) [pdf]
Yeah, that is another dark corner. I was not quite precise (I forgot this behaviour existed): $ expansion does allow for parentheses as well, so that arrays work. Meaning $($b) is the same as [set ($b)] which is element $b of the array in variable {} (empty string; that is the name of the variable). The docs [1] say:

> $name(index)

> Name gives the name of an array variable and index gives the name of an element within that array. Name must contain only letters, digits, underscores, and namespace separators, and may be an empty string. [...] Command substitutions, variable substitutions, and backslash substitutions are performed on the characters of index.

So that means:

    set b a
    set (a) a  ;# this sets element a of the variable {} to a
    puts $($b) ;# prints that element
    info vars  ;# all variables, note that {} is in there
    puts $($($($b))) ;# Of course this works...
[1] http://www.tcl.tk/man/tcl8.6/TclCmd/Tcl.htm#M14
suyjuris··on Data Definition and Code Generation in Tcl (2014) [pdf]
Some of these things do not quite work this way, but they demonstrate some interesting peculiarities! The eval should be expr, as you are trying to evaluate a mathematical expression, not a command. Similar to the common footgun:

    set a 1
    puts [expr $a + $a] # Wrong!
    puts [expr {$a + $a}] # Correct
Also $$b expands to $a, not 5, as dollar expansion stops at the next non-alphanumeric-or-underscore character. This would usually be written as [set $b] (equivalent to [set [set b]] ), utilising that the set command outputs the value of the variable with that name. Similarly, [set var[set $b]] for the last line. Also, # is only a special character at the beginning of a statement, so comments have to follow a newline or semicolon.

In the “everything is a string” department, my favourite are block comments:

    if 0 {
        This is a comment.
    }
You can write any kind of comment in there, even special characters like $undefined or [undefined] which would cause errors in normal code. Only wrongly matched {} would be a problem.
suyjuris··on Data Definition and Code Generation in Tcl (2014) [pdf]
Reading this really reminded me of some of the fascinating/crazy things Tcl is capable of, all based on a simple programming model focused on strings. Like, want to pass a reference to a variable? Simply pass the name of the variable to the function and then do

    proc f {varname} {
        upvar 1 $varname var
        set var ...somevalue...
    }
The upvar “links” the local variable var to the variable named $varname in the scope of the calling function. Or maybe you are in dire need of a control construct that loops thrice? No problem:

    proc do_thrice {code} {
        foreach _ {1 2 3} {
            uplevel 1 $code
        }
    }
Okay, this does not handle break, continue or error propagation (you can do that also, but it would be a bit longer). You can use this like so:

    set text Go!
    do_thrice {puts $text}
The variable text is not visible inside of do_thrice; but the uplevel executes the code in the scope of its caller, so it can read and write to the local variables just like an ordinary loop.

Of course, in ordinary code you should mostly avoid this kind of stuff. Though apparently uplevel is used by NASA, of all people, so I guess it is fine!

More fun stuff: You use the built-in proc to define a new procedure, but you can replace it by your own, e.g. to insert profiling code at beginning and end. (Hint: If you try this, use uplevel when calling the built-in proc, to avoid namespace problems.) You can parse and rewrite code at runtime (of course) which I once used to insert “breakpoints” at runtime for my program to debug itself.

suyjuris··on The Sci-Hub Effect: Sci-Hub downloads lead to more article citations
You probably know this already, but for the benefit of others: While it depends on the subfield, a lot of computer science and mathematics papers are freely available.

1. Searching for the title often gives you a PDF in the first few results already. Authors usually have the right to upload a version on their personal website or arXiv.

2. There is Google Scholar [1], which has links to PDFs on the right of the result (if it knows one). It is better at this than regular Google search, in my experience.

3. Manually searching on the author's website (or former website, if they moved) sometimes proves successful, although this is relatively more effort.

4. As mentioned, writing an e-mail to the authors works as well. (If you buy a paper, the authors get nothing, so there is no incentive not to share it.)

[1] https://scholar.google.com/

suyjuris··on What’s New in macOS Big Sur: Human Interface Guidelines
> Why do you think a system that doesn't make it difficult to completely destroy it with one command is a bad idea?

This does not seem very charitable.

It is fine if the system warns you about doing potentially dangerous operations (which --no-preserve-root amounts to) but it must not prevent you from ignoring that warning.

suyjuris··on Create diagrams with code using Graphviz
I was looking into that a while ago, but sadly I did not find anything great. Back then I wanted to draw animated Binary Decision Diagrams, so I had to come with an incremental (and simple and fast) layout algorithm, which could determine positions for new nodes without interfering with the original graph. The result works fine, but it did require a fair amount of tweaking. (The comments document these tweaks extensively [1].)

If you want to write something more general, then that would probably be much more complicated.

[1] https://github.com/suyjuris/obst/blob/feb8e766ce226ca1afe862...

suyjuris··on How the Magic: The Gathering Color Wheel Explains Humanity
Just off the top of my head: Feedback (545, 199), Human Nature (329), Teaching (415), Creativity (77, 551), Complexity (455), Stand-Up Comedy (347, 543), Interviews (335).
suyjuris··on How the Magic: The Gathering Color Wheel Explains Humanity
Drive to Work [1] is a great podcast. Most of it is, of course, about MtG, but there are a lot of episodes about various things like writing, creativity, or communication. Mark Rosewater is the head designer, which means that he is responsible for creating the general structure of a set [2] and not the various stages of fine tuning that happen later on.

So there is a lot of content about designing for humans and little about detailed number-crunching and game balance.

He also explains most terminology and concepts, so a passing familiarity should be more than enough to understand the MtG-related content.

Also, no ads.

[1] https://mtg.gamepedia.com/Drive_to_Work

[2] Cards are released in groups, called sets. A set (usually) takes place on a particular world and is connected to a part of the larger story, which are reflected in its gameplay.

suyjuris··on Simplifying Board Games
I have listened to a fair number of people explaining board game rules and I feel quite strongly that most of these explanations present too much information at once. Often someone reads the rules, and then basically tries to present them all at the same time, which leads to people unfamiliar with the game feeling overwhelmed and not processing the information. Later, when playing, you can observe the actual learning happen, once people ask what moves they can make and observe what the other players do.

I think that it is much more efficient to simply drop the first part and go straight into the game. Whenever an action is required, simply tell the person their options and focus on reducing the information as much as possible.

Like, if you were teaching someone to play chess, you could prepare the board and play as white, while your friend plays black. Then move a pawn while explaining the way pawns move. Let your friend move a pawn. Continue until the capturing rules for pawns become relevant. Explain those. Then, one-by-one, introduce the other pieces and their movement over multiple turns, when they can actually move. At some point, a check will happen (or you can make it happen). Now you can go into the check rules, and how a game is won. There is no need to explain everything in the first game either, things like castling, pawn promotions or en passant can be postponed until they become relevant.

Also, there is no need to involve strategy. The focus should be on teaching to play, i.e. take valid game actions, not on how to play well. In addition to being unnecessary information, there is also a lot of fun in figuring things out by yourself.

Usually, for board games the designers thought about the best way to teach the rules and the manual is helpfully structured in that way. So it will first describe how to prepare the game, then the turn structure, then the possible actions, and so on. Often you can start a game parallel to reading the rules, which is handy when no one knows the game.

Simplifying the game, as in the linked article, is also quite useful. There are some good examples of explicitly changing the games to be simpler, but you can also do some more subtle manipulations. For example, in Go (the board game, not the programming language) beginners play with the full rules (which are already simple enough) but on a smaller board, which leads to shorter, less complex games. In Magic: The Gathering, you can teach someone by preconstructing the deck to contain only simple cards. (I have seen some board games incorporate this as well, but there it is usually framed in terms of 'extensions' to the rules.)

suyjuris··on New fuzzing tool finds USB bugs in Linux, Windows, macOS, and FreeBSD
> Here's how triggering UB ends up as a vulnerability

To be fair, dereferencing NULL ended up as a vulnerability due to

1. the optimiser removing the subsequent NULL check, and

2. the zero page being mapped.

While 1. may happen, depending on how sophisticated the compiler is, 2. was already a security issue and is 'almost always' not the case.

suyjuris··on The Ten Commandments for C Programmers (1987)
Yeah, I certainly agree that the features cost you even if you do not use them.
suyjuris··on The Ten Commandments for C Programmers (1987)
I would much rather recommend something like "C with bounds-checked arrays" than a form of "standard" C++ to newcomers. Yes, StackOverflow will not help much, but I think avoiding the huge amount of features that the rest of C++ brings is well worth it. You are probably not advocating for dumping everything at once onto a beginner, so why not pick a subset that is both really small and gets you quite far?

> You still have to learn how exceptions work and why avoid them, what is heap and how to disable it, what are pure virtual classes and so on.

Do you mean later on? As I see it, you do not have to learn about the things you do not use and can concentrate on the basics. Once you are comfortable and need to venture out into projects where other parts of C++ are used, you would need to, of course.

suyjuris··on Ask HN: What's your quarantine side project?
Nothing too fancy, I have been writing/rewriting some of my personal libraries. I finally gave in and wrote an OpenGL abstraction, because dealing with shaders manually was such a pain. Now I am working on a simple GPU font renderer, which is hopefully easier to use than my earlier CPU rasterisation based approaches (no need to snap to pixel raster or to pack things into a texture, can deal with both small and gigantic letters).
suyjuris··on A non-moral dilemma about cheating, but it brings up some points (2019)
I do not think that this make it better for the student. They still cheated, only instead of acquiring the actual answer they obtained the information whether their answer was correct. (Based on their knowledge of the situation.) So they acted unethically to gain an advantage, but instead sabotaged themselves.
suyjuris··on Show HN: Micro-mitten – Research language with compile-time memory management
> One thing I'd like to see in modern languages is to encourage and simplify working with an (almost) entirely static memory layout, and make manipulations inside this static memory layout safe.

This sounds interesting! What do you mean by (almost) static memory layout? Fixed sizes for everything in a contiguous region, or multiple growing arrays, or something else entirely?

In recent time I have written a few programs in a way that uses only realloc inside dynamic arrays for memory management and never frees. This leads to a big semi-global struct holding all the dynamic arrays, which I am reminded of. (Local functions can then take those arrays, use them, and give them back once they return.)

suyjuris··on No cookie consent walls, scrolling isn’t consent, says EU data protection body
I do agree with you that you should be able to freely exchange your privacy as you see fit. But the difficulty, as I see it, lies in determining whether the exchange is truly free or coerced by some means. The GDPR takes a strong stance on this (that consent is only freely given if withholding it would have no drawbacks) and it does have false negatives, i.e. situations where the exchange was fair but prevented.

However, there are two reasons why I think this is still reasonable (with 1. being more important):

1. The reality of the current situation is that invasions of privacy come bundled with other services, which you are pressured to use due to external factors. So I believe that the vast majority of cases are modelled well.

2. I see a privacy as similar to herd immunity, in that society benefits if lots of people have it, even if the individual does not profit from it directly. (In particular, it may prevent certain kinds of power from accumulating or centralising.) In these kinds of situations it can be necessary to restrict individual rights to achieve optimality.

suyjuris··on No cookie consent walls, scrolling isn’t consent, says EU data protection body
Privacy is a consider a basic right in the EU, so no, you cannot operate monetisation schemes that violate it. It would be like having a 'by entering our restaurant you are agreeing to our reduced-hygiene policy' sign at the door. If a business cannot survive with clean hands, then it should not.
suyjuris··on I could do that in a weekend (2016)
The author seems to have given this topic some thought [0].

Personally, I did not experience any problems reading it on my ~50cm wide monitor.

[0] https://twitter.com/danluu/status/1228041917272715264

← PreviousPage 3 of 4Next →