Hacker Newsnew | past | comments | ask | show | jobs | submit | Splizard's commentslogin

Tagged unions can be implemented in user code, you dont actually need language support to use them.

https://github.com/splizard/tagged


This is only a small piece of the story for what people say when they want tagged unions. Without all of the ancillary support in the language, like exhaustive pattern matching, it really doesn't count.


You can also add support for exhaustive switches on tags.


Just as a linter config though?


No, by leveraging unkeyed struct initializers as the switch case pattern, which the Go compiler does exhaustiveness checking on.


The C++ committee said the same thing, and gave us std::variant. They are painful to work with and do not really deliver most of the benefits people want.


That is a LOT of code (very ugly code, I would add) that could be replaced by `type Float = float32 | float64` in a language with actual support for union types.


Tagged unions are not union types. A union type is a supertype for any arbitrary collection of types, but a tagged union aka sum type is a single type with multiple data constructors, and does not require subtyping to be implemented.


exactly


What are your plans around the maintenance of this project, how would you feel about solo being incorporated into the musl build for graphics.gd ?


Small nitpick but Go doesn't really have any YOLO C/C++ code in its runtime and standard library.


Yeah what I said is true of TS and C#, but not of Go.

Go’s situation is nuanced since a lot of Go code does rely on unsafe C or C++ deps, but I have no idea how generally true that is. Also Go’s protections fall apart under certain races, which isn’t true in Fil-C.


Races in Fil-C allow access to one object through a pointer to a different object if there's an attacker-controlled offset involved.

Fil-C's safety guarantees therefore fail to apply in this situation.


Nonsense.

In a race, you at worst access an object you could have loaded from whatever field you were racing on.

In Go, you can bypass all protections and corrupt all of memory if you race on structs (I think).


> In a race, you at worst access an object you could have loaded from whatever field you were racing on.

Suppose a pointer ptr is initialized to foo and transitions once to bar; suppose also that x is attacker-controlled. Then,

  T1: T* p = ptr; if (p == bar) p[x] = 7
  T2: ptr = bar
A program can observe p == bar (testing the address bits) but still permit a write to foo through p (allowed by the stale capability bits after offset by attacker-controlled x), allowing T1 to perform an unexpected mutation of foo.

No, you do not always trap in this scenario, as you've claimed repeatedly on X. You perform the capability check after combining p and x. If an attacker sets x == foo - bar, then p[x] refers to memory inside foo even if p == bar.

Because (for understandable reasons) you don't insert a memory barrier between a write of a pointer's address bits and its capabilities, use two-word atomic accesses, STM, or in any other way synchronize writes to pointer addresses and capabilities, programs with data races can observe arbitrary combinations of linear addresses and capabilities that go along with them.

Plenty of exploit chains have had humbler beginnings.

This access-foo-through-pointer-to-bar scenario can't happen in Java. It can't happen in CHERI. It can happen in Fil-C. Yes, T1 at one time had a capability on foo, but the programmer intent is clearly to mutate only bar, and Fil-C allows an execution that mutates foo instead.

Elsewhere, you've claimed such executions cannot be exploited. I am skeptical of this claim given previous exploits that began by the camel poking its nose through similarly innocuous-seeming holes in the tent.

Fil-C cannot fully protect C programs from exploitable memory corruption caused by violations of the C virtual machine. 99.9% of practical ones? Sure! Fil-C is good stuff. But there are holes (not only here, but for arenas, intra-object corruption, etc.), and these are holes that safe Rust prevents. Fil-C and Rust rules prohibit different (but mostly overlapping) classes of exploit.

Could you define Fil-C's behavior as "memory safety"? Sure. You can define words to mean anything. You cannot, however, define Fil-C as something that just deletes the security implications of bugs in existing C programs. Does it mostly achieve this goal? Sure. Does it supply comprehensive coverage? No! It's a hardening tool, not a panacea, and it would behoove you to represent it as the useful tool it is, not magic pixie dust that makes C safe.

Please stop ruining a tool as good as Fil-C by claiming it does things it does not and cannot.

> In Go, you can bypass all protections and corrupt all of memory if you race on structs (I think).

This is my understanding as well. I'm glad we agree, opinions on Fil-C memory model counting as "safe" aside, that Go is awful.


The “bug” in your example hinges on this:

> if (p == bar)

It is not in scope of memory safety to make sure that logic not related to memory accesses works as you expected.

In Fil-C, the integer pointer value (the intval) is not trusted. You could get it wrong with things more sexy than races (integer overflows or just plain bad math). Fil-C just guarantees that your accesses obey the capability model, which is true in your example - the only object the program can access is whatever object the capability you loaded points to.

You’re being disingenuously imprecise when you use this framing:

> access-foo-through-pointer-to-bar

In fact, you can only access foo if bar’s capability referred to foo, and that can only happen if the thing being raced on (the pointer in shared memory) had a prior store to it that had foo’s capability.

Hence, this isn’t an arbitrary memory access. This is a memory access that obeys the capability model. It’s a memory access that would have been possible even if the program had no race.

> Please stop ruining a tool as good as Fil-C by claiming it does things it does not and cannot.

You are mischaracterizing the issue to make it seem like it’s a memory safety issue, when it’s not. I think that is doing more damage than anything I have said


> It is not in scope of memory safety to make sure that logic not related to memory accesses works as you expected

This logic is related to memory accesses. This is not an issue that can occur in systems that provide the memory-safety guarantees that the words "memory safe" usually name.

You can't escape failure to meet a public definition of a term by adopting a private definition. The English language has a term for this pattern.

> You’re being disingenuously imprecise

You are the one being imprecise. You claim that because T1 could access foo at some time in the past, it's okay for a subsequent execution to access foo when the program text limits the access to bar. The temporal history is irrelevant. You are taking language that applies to inter-actor access control and applying it to invalid execution detection.

If T1 and T2 were, say, mutually untrusting actors over a network, that T1 had a capability at one point would be a valid defense. We're talking about a totally different scenario, not an object-capability security system, but preventing attackers turning illegal C into various kinds of exploit, e.g. EOP, information disclosure, and so on.

It does not matter that T1 used to have the capability and could have used it. We're talking about an attacker using an exploit to make T1 do his bidding, not T1 itself being a hostile actor running in a sandbox.

You can't just define the problem away. Real-world C has these races. They've been exploitable. Your system doesn't close them.

> Hence, this isn’t an arbitrary memory access.

Not arbitrary, true. Irrelevant. It's a cross-object access that violates programmer expectations and is likely exploitable.

> This is a memory access that obeys the capability model

You're using the English words that denote a strong guarantee in the security community and using them to describe your weaker system.

> I think that is doing more damage than anything I have said

Damage to what? You can't fix this problem in Fil-C without introducing atomics to every globally-visible store path, so you're going around the internet trying to play definition games to define it out of existence. The only damage here is to people who think Fil-C provides stronger mitigations than it does.


yea this headline is pretty disgusting


Maybe you could look at using some AI assistance to provide some real 'useful' feedback to the OP about what made you lose interest, as your false confidence in some opaque 'AI-detection' heuristic is lazy and only harms individuals who are trying to find effective ways to share information.


The AI tells are quite literally what made me lose interest. They help me filter out dozens of AI slop posts daily so I'll be keeping them thanks. They're lazy by design. You can generate a good looking post in 30s, I can't afford to spend 5 mins reading each one on its merits.


You have to tell musl to use mmap instead of brk. You're right that it doesn't work in all cases but as long as you switch TLS on calls (and callbacks), at least with a project the size of Godot, you can approach a workable solution.


> You have to tell musl to use mmap instead of brk.

How do I do that? Is there a documented configuration of musl's allocator?


you can patch musl, to initialize the brk state as -1 and then it won't use it.


If only there was an easy way to fund all the Open Source programs you like and use, so the projects who struggle with it, can put more focus into design.

Seems like a win-win, take my money solution, for some reason the market (and I guess that means investors) are not pursuing this as a consumer service?


The issue appears to be cascading internationally due to internal dependencies on us-east-1


The problem with configuration formats, is not syntax, or abstraction, it's the lack of consistent language server integration, it's problem when I can't lookup the definition for a key, the expected type, or quickly jump to definitions that clearly show which keys are available to configure.


To be frank, the clear problem with configuration format is that people have configurations so complex they probably should use something else.

Example: We are programming a backend for a blog. If we were to not use templates, but instead try to get that functionality via the webservice configuration we would have to "invent" some format that gives us the flexibility of templates within let's say a YAML file.

Needless to say that would be a horrible idea. Maybe I am being naive here, but I have yet to be convinced of the fact that it is really configuration formats that are the problem and not what people try to abuse them for. I have yet to work on a project where TOML wasn't enough for actual configuration.

Usually when I need something more complex than what can be done with TOML it is a sign that this needs to be handled differently. Via templates or with a database or making a special DSL-like script file. E.g. if you're using python nothing (except security considerations) stops you from allowing users to use a python file for configuration. If your configuration needs are really that complex, why not use a real programming language for it?


Two examples of complex user facing configurations I can think of are pretty trivial to implement:

- Decision tree, where you only need comparison operators. The leaves are a specified list of actions.

- actions list with macros (variables). You can be fancy and add some conventions for arrays.

Anything more that that should just be a programming language. And if the relationship is adversarial (saas), you should really think hard about needing something that complex.


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

Search: