The Standup with ThePrimeagen - Memory Safe C
Episode Date: November 17, 2025Thanks to this week's sponsor: Code Rabbit If you're tired of developers just replying with LGTM, then you NEED Code Rabbit. An actually useful application of AI where it can use your own rules, lint...s and more to provide instant feedback in your editor OR a review on Github. https://coderabbit.link/primeagen-vscode Fil-C creators: https://x.com/filpizlo https://twitch.tv/ThePrimeagen - I Stream on Twitch https://twitter.com/terminaldotshop - Want to order coffee over SSH? ssh terminal.shop Become Backend Dev: https://boot.dev/prime (plus i make courses for them) This is also the best way to support me is to support yourself becoming a better backend engineer. Great News? Want me to research and create video????: https://www.reddit.com/r/ThePrimeagen Kinesis Advantage 360: https://bit.ly/Prime-Kinesis 00:00:00 - Intro 00:01:29 - Fil-C Demo 00:07:56 - Security 00:11:52 - Game Engine Use Case 00:14:20 - What cant it do 00:18:02 - Different to ASan 00:23:57 - How Fil-C works 00:36:38 - Choosing Fil-C over Rust 00:51:31 - Outro
Transcript
Discussion (0)
You guys ready to talk today?
Today is a pretty good topic.
Are you guys ready for today?
I'm ready.
Okay, yeah.
I mean, I'm not ready.
You guys don't know.
I'm just ready.
We're going to start anyway.
Yeah, yeah, yeah, yeah, yeah, yeah, yeah, yeah, yeah, yeah, yeah.
Anyway, sorry.
Today, we are talking about Phil C, the memory safe C.
Is it useful?
Is it good?
Is it the future of C?
As always, we have with us, Teage, creator of a C-based memory course on boot.
Where you get to go over how a language.
What was that, DJ?
Good point.
Yes, great points.
Okay, well, don't interrupt me saying that I'm like in the middle of a really strong intro.
All right, anyways.
As always, we have with us, Teage TV, creator of a C-based memory course on boot.com
where you go over how to create a garbage collector and Casey Muratory legendary C-Chad game programmer.
Check out Computer Enhance.com for his amazing courses and lecture.
And we also have a special guest with us today.
Low-Level Security Extraordinaire and also Seed at C&Asum, Chad.
Check out low-level.
Dot Academy for amazing courses and all your low-level needs.
Now, hey, no problem, buddy.
So now, let's talk a little bit about Phil C.
gets to say a comment and it didn't break the intro.
On the last one, suck it, nerd.
He said it cleanly.
He got it in there, T.
It was like part of the flow.
I was part of the flow.
Talking, T.J.
And you just were like, hey, that's a great point.
I didn't even think about how that would be relevant to this today.
So I was surprised.
Go ahead, Brian.
Anyways, just for everybody to understand a little bit about Phil C,
here's some basic C code along with a special standard fill up at the top that's brought in.
That allows a special kind of printing character called the capital P.
And in there, it will actually print out, hey, look at this.
This pointer actually has three values in it.
You, the C, developer, will only see just, you know, the integer.
But underneath the hood, there's actually some extra information stored.
And this actually shows it's lower and it's upper bound.
You can see that we allocated 16 bytes, and of course there's 16 bytes difference between the lower and the upper.
That is fantastic.
And with that, it allows for some special behavior.
So here we go.
We malix 16 bytes again.
I attempt to access byte 42, or technically the 42nd index into here, which would be out of bounds.
And Phil C says, ha, ha, ha, ha, ha.
I've thwarted such an easy and very obvious thing.
Now, some of the things about Phil C that makes it a little bit unique and probably is going to
going to make a lot of people mad is it's actually garbage collected that's right it's a c that is
garbage collected so if you look underneath the hood even if you call free it does not technically
free it marks it as being freed and then later on the asynchronous multi-threaded behind-the-scenes
garbage collector will go and free that memory so it's a very if this is not your grandfather's
see okay this is this is modern see and what he means whatever that's fine good one t you
I'm just saying he made one. It's fine. It's okay. Keep going. They have garbage collector and C for a while, but yeah, that's okay. Go ahead.
Yeah, I know, but it's not, that's not like your standard operation and C. People don't think C, oh, yeah, that garbage collected language. Like, that's not the first thought that comes into people's heads, whereas this is garbage collection at all times.
Yeah, standard. Standard C does not have a garbage collector.
That is true. Right. You're talking about some additional thing when you talk about C garbage collection, right?
Yes, yes, yes. Whereas this is going to be like your standard experience is actually garbage collected. Now, obviously, Phil C. does.
And with a lot of performance penalties and runtime checking.
Like when I did that little check into P-42, it obviously did a runtime check on that when you attempt to run it.
It crashes your program successfully.
And so that is a yes, TJ?
I was wondering, do we have any bouncing balls to show the performance penalty for charts?
Because I feel like I can't, as you said performance penalties, I literally wanted to slap myself in the face that I did not bring a bouncing ball chart.
to benchmark this for Casey.
I'm so angry.
I'm so angry.
As you can see from this diagram.
Very scientific.
There are some performance penalties.
It's like, no, actually, I can't see from that diagram because the diagram sucks.
That's why I can't see it from that diagram.
That's pretty funny.
Look at all these engineers sitting at their neat little desks.
It takes dirty work to keep a code base clean.
Every day sickos are out there committing unreviewed
code and when that happens, linters won't save you. You need someone like me.
Feet your free scrum bag. Who are you calling scrum bag? What's this slop you're trying to push?
Unnecessary comments? Global state? Nested ternaries? Oh, my bad. I didn't even read the code yet.
You disgust me. Step away from the keyboard. Just let me explain. Is that a mouse? He's
merging to prod. You have the right to remain silent. Anything you push to GitHub,
Canon will be used against you. You have the right to a debugger. But if you have you
You cannot afford one, a public stack race will be made available here.
And one more code criminal off the streets where they belong.
HR.
Look, I didn't yet...
I know I didn't review any of the code, but I was going to have CodeRabbit review it from the start.
With one-click fixes, install enforcement, I don't need MerchCob.
I would never merge I reviewed code, but a first pass with CodeRabbit always makes things go faster.
Actually, you can try it too at coderabbit.ai.
Next week on Merge Cop.
The Diffler's out there, and I'm going to be the one to deprecate him.
So to kind of wrap it all up, so everybody understands how Phil C works.
The runtime impact of Phil C is going to be somewhere between 1.2 to 4X is what I have seen.
And then you will see comments on the Internet that say something along the lines up.
What's 20% these days?
Nobody cares if you lose 20% performance, which I know that Casey will probably lose some sort of sleeper hair over with that kind of comments on the Internet.
Wait, how do we get from 1 to 4X and go from that to 20%?
Well, because 1.2 would be, you know, 20%, but then 4% would be...
Oh, you mean, if you just took just the minimum, as assuming that you were going to get the minimum for some reason without evidence?
Okay, sure.
Can I say, there is another performance penalty?
Can I, can we talk about that really quickly?
Yeah, yeah.
Before I do that, I just have to...
I'm going to be a little bit on the rust side today, so I came prepared.
Oh, no.
Perfect.
Okay.
Hey guys, it's Rustyge checking in today.
The other problem is that there's a serious memory additional performance constraint here
in the sense that it's going to allocate a lot more memory for lots of different kinds of programs.
So I just wanted to make sure that that's clear.
It's not a zero-cost abstraction.
Okay, it's not a zero-cost.
So, Prime, you may continue.
Actually, Teage is very, very correct.
It is not, in fact, a zero-cost.
cost abstraction.
Anyway, so I just wanted to talk about this because the thing that really sparked all of this
was that pseudo-RS is kind of this new brand of pseudo.
It's the new pseudo on the block.
And Ubuntu saying, hey, we're using it.
But all the comments are like, why?
What's why are you doing?
Like it seems to be a, at least it appears, I don't know if it's actually true in real
life, but in Twitter life, it appears to be a largely negative experience.
And so with that in mind, some people are saying, well, why don't you just use Phil,
Phil C, the performance of pseudo is negligible, and you can get 90% of the safety without having to deal with Rust and a rewrite and rediscovering all the bugs.
And so that's why we have with us Casey and low-level learning.
TJ is just here for fun.
And so therefore, I think it would be fun to start probably with the security side, just because I think that that is probably the most poignant or at least the most reasonable place to start when it comes to a memory safe C.
Ed, if you'd like to kick off any talks about that, I have a lot of questions about it, but any initial statements?
Yeah, I mean, so I guess to kind of kick this conversation off, right?
What is spawning this?
If you guys aren't aware, pseudo, you know, well-known, well-loved program that tends to be the target of a lot of vulnerability research
because it is one of the most widely available, widely used set UID binaries, right?
It's a binary that runs its root and use it to run things either as root or somebody else.
And so a memory corruption vulnerability in pseudo
obviously violates a pretty hefty, pretty scary security boundary.
And so as a result, there's a push to re-rate a lot of bin-utils,
one of them being pseudo, in Rust, right?
Kind of a cool idea.
This also, for some reason, kicked off an effort to, like, rewrite all of the core
utils in Rust to include, like, Echo, Cat, Sed, which is a whole other conversation.
But unfortunately, despite it being written in Rust, shocking, I know,
I think there were two CVEs that came out recently.
in the RS implementation of pseudo.
So it kind of begs this bigger question.
I think, you know, we've talked about this in the previous episode that I was on with Casey.
You know, all because you write it in Rust doesn't mean that you're going to get the exact same behavior.
And if you can't confirm via some set of testing that you have, you know, not regressed at all in your functionality,
then you're potentially introducing new vulnerabilities to the code through logic errors.
And that's, I think, exactly what we saw with pseudo-RS.
So instead of rewriting everything in dollar sign,
new lang, and I'm sure we're going to iterate on new lang every 20 years, why not drop in a new
compiler that has sanitizers, that has intermediate representation checks to put in on an arbitrary
pointer the vector size, right? And that's what Phil C does. I have not used Phil C personally. I'm
kind of curious, Prime, how it went for you. Overall, I think Phil C is a great idea. There are
some compact issues. You have to be compatible with the LLVM tool chain to make it work, which is kind of
an issue for some pieces of software, but generally, great idea.
I love the concept.
So that's kind of my first take.
Casey, what about you?
I'm on the same page.
Essentially, like, rewriting something in Rust to me is usually a pretty bad idea,
because the problem is that your really Rust can only guarantee you a couple security
things that it's specifically designed to do,
but all of the other ways you can have bugs are still there.
So it doesn't really handle all of, like, your logic errors or things like that
that could result in your...
your program doing something potentially catastrophic, especially in the case of like a core utility, like pseudo.
And so really, like, I would never have, like, I would be like, don't do that.
Like, like, we know that there are memory, you know, safety problems in the languages these were written in, but they've been kind of beaten out over the years.
And we can keep looking for them and so on.
And so rewriting something in Russ like that is just very dangerous and I think ill-advised.
So something like Phil C is kind of a very nice middle ground, I would say, which is that like, we, hey, we can.
can preserve the logic integrity of this thing that has now been battle tested so that we're pretty sure that we've found a lot of the logic errors that I'm sure we're in there originally that we've now kind of gotten out over the years as people found them.
But now you can also get this added layer of memory checking just to make sure that memory things we haven't found yet, maybe this will protect against those.
And then you're really just down to like, okay, are there bugs in Phil C itself, right?
And, you know, maybe those take a little while to suss out, too.
Like, maybe there are some edge cases that, you know, will be found.
But until then, it's like that seems like a much better – that would be true of Rust as well, right?
Like, there's no difference between Rust and Filcy in that sense.
You can always have bugs in the implementation of the memory safety.
So it really does seem like a much more sensible approach if you're just talking about our goal here is to make sure that we're providing the safest possible version of something like pseudo.
Yeah.
Okay, so I mean, those are all kind of like, they feel like intellectual arguments, more than actual, like, practical arguments.
Do you think there's an actual practical argument to say that Phil C is going to be something that is, that is, like, fully usable?
Like, Casey, could you use Phil C in a game? Or would you even ever consider using something like Phil C in a game engine slash game?
Well, I mean, you'd have to have some reason why you felt like what it's offering you is important.
So, you know, there are some ways in which you could imagine this being.
important. For example, if you have a lot of user-generated content in a game where potential
bad actors might be trying to use that ability to upload content to create sort of security
exploits, right? You can imagine something like Roblox or Fortnite or whatever, where they're
kind of constantly trying to increase the amount to which their users can contribute new games,
new modes of play, whatever.
You could imagine something like that where there are cases where you're very scared
about things like memory protection and stuff like that.
And so I could see maybe some arguments in certain specific scenarios where you're like,
we really need this.
So we're going to take this isolated part of the engine and maybe we will use something like
Filci.
We'll accept the performance hit, but we just really need this.
We need is all the security we can get.
But for the majority where you're talking about,
talking about just running a game in an isolated context on someone's machine, it's unclear
what you really need this for, right? For the average game development, it's not really, and I
don't, I mean, the person who created Phil C works at Epic, right? They are working on, I think
they work on Verse, the Epic, like Epic's Fortnite programming language thing. And so, like, you know,
I would imagine most of like an Unreal Engine or something that wouldn't really adopt
something like Phil C, but you could see some specific cases where that might be important.
And for example, Verse, which is their language, that would be a case where he probably is
employing some of these techniques there. I don't have any inside knowledge of that, and I don't
work on that. So that would be my take on it, is you'd have to be in an area where you really
cared about it, because otherwise I'm not really sure what you would need it for. Does that make
sense? Yes, I think that does make sense. I mean, where my big misunderstanding probably just comes
from is that I don't understand.
I was trying to read some of the things with the differences between like A-San and UB-San
and how that,
how Phil C actually can circumvent some of those problems.
But at the end of the day, TJ brought up really good points because he's being the resident
Rustav.
There are things that Phil C just can't do.
And they even,
they even shouted out,
which is like file handles.
They are something that we can't,
that can't be represented in the same kind of context.
Well, here, I'll give, I'll give the example.
First off, that's probably the longest
to Rust users ever gone without speaking,
so I just would like that to go into the record
as a moment for allowing other people to speak.
I do have Rust running in production right now,
so that is something that also most Rust users have never done.
So I would put myself ahead of almost every Rust user in the entire world.
Hey, same guy, listen.
Yeah, so just throwing it out there as two things
that make me very qualified to talk about this.
But I do want to, can I, I need to say one thing, though.
You also did the zero to I use Rust, by the way, at the same standard rate as any Rustev who starts speaking within the first like five seconds.
You mentioned the fact that you used Rust.
By the way.
By the way.
I don't, I thought I wasn't allowed to run Rust C unless I did that.
I still need to run Rust C sometimes.
So I don't understand.
So, okay, anyways.
So this is on a serious note instead of meming about Rust users.
This is not a reason that I would rewrite a program.
So this is like a different class.
So if we want to start, we can maybe talk more about like the rewrite situation first
and then talk about, you know, like if you were starting off a new project, which one you might want to choose in pros and cons.
because the thing that I think a lot of people are missing,
and Ed and case you guys both alluded to this at the beginning,
maybe I have to take my Rust hat offer this to say something nice about Phil C.
It's like, you can't just rewrite everything.
It actually doesn't work.
Like, we don't have enough time or resources or a bunch of other things.
Even just like if you think you can bug for bug, remake it exactly right and handle every case,
it's just not realistic to make that happen.
Like even, like, I think probably I could run Neovim, you know, at like, even at Phil C's current worst case, 4x slower, and Neovim would still feel fast and good for me, right?
You know what I'm saying? Like, even if it was four times slower. And that's assuming, and I'm, I see as well, we've got Pizzlinator in the chat, who is the creator of Phil C, by the way.
like Phil C is gonna I think get faster than what it is right now as tends to happen for people who actually care about software and making excellent things
so it's like I could run neovim and then I would not be able to be exploited by certain cases of memory safety bugs right because I'm sometimes running slightly untrusted things in neovim I'm running someone else's code running like via a plugin or other things like that so it's not realistic to just say like neovim just rewrite it
in Rust. That's just do it. It'll be easy. That's insane behavior. That's a, that's a not a
realistic scenario. So that's the thing, for some reason, I feel like a bunch of Rust people are just
like talking past it of like, you could just have a safer world today. In fact,
Graydon Hore, creator of Rust, said more memory safe programs is better for all of humanity,
right, in talking about Phil C. So anyways, yeah. This may kind of be jumping backwards in the
conversation a little bit there, but Prime, I kind of heard you, I think, sort of raised the question.
You said, like, I have questions about, like, what's the difference between, like, address
sanitizer and using something like Phil C, right?
Yeah.
And I thought maybe that might be something that's worth, like, talking about a little bit.
Yes.
Yes.
Because I've A-Sand a few times in my life.
I'm no A-San expert.
And so I just know that it's caught.
I've done silly things with standard vector in the old C++ world where they're just like,
you're doing stupid things and I was like, oh, that is a stupid thing.
Like, I just didn't know what I was doing.
Right. So, just to be clear, the idea behind things like Phil C and also just there's like
kind of a broader security idea here, actually, than just Phil C, which is that arm chips,
or the arm specification, I should say, and certain vendors supply actual hardware support
for the kinds of things that Filci does.
It's not exactly the same as for there.
Philcy does things beyond what this hardware would be doing for you.
And we can talk about that a little bit.
X64 spec also has now introduced this,
although I guess I haven't really followed closely enough
whether anyone's shipped any of it yet.
But like there is a specification for it, right?
And so I'm assuming that like zions and, you know,
epic processors down the line will have this for servers or something, right?
I haven't followed out the update.
But Apple M-series chips now, for example, do implement this arm, this particular arm extension.
Anyway, these things are not designed to analyze your program when you're developing it and tell you whether they found security vulnerabilities.
They're designed to actually just stop the program any time it's running when it would have done something bad.
So the idea here is to make sure that something that address sanitizer may,
wouldn't catch because when you were running the program you never exercised the code path that happens to do this thing or whatever else you know like the static analysis part can't catch things or what you know whatever you were using this is designed to basically say look the actual runtime model of this thing literally can't do these bugs when they would have happened the program simply halts it's basically just a thing that says when you would have written to a piece of memory that was actually a different piece than this pointer was something
supposed to ever be able to write to, we just stop.
The program faults, and it closes.
And so, again, it doesn't really prevent the bug in the sense of the program working.
The program still doesn't work.
What it does is it stops it from turning into anything other than basically a denial of service attack, right?
So does that make just light sense, just to start with?
Yeah, yeah, yeah, yeah.
Okay.
Yeah, there's all the talk in chat right now about ASAN.
We should probably highlight, like, ASAN, for example, is not meant to be an exploit
mitigation in the sense that you use ASAN to block hackers, right? Because all ASAN does is put a
predictable pattern as a shadow region and a memory space so that when that is corrupted, it's like,
hey, it's not the same. You probably should fix this. But the pattern that it puts is
is deterministic, right? So like an attacker could just put the FAs on the right spot. And,
you know, that would not trigger ASAN while still violating memory safety. So ASAN is more like a
a tool that you compile your code with
to make it as fall over as fast as possible
as possible to put it in your fuzzling rig in CI
so that in two weeks when your fuzzling is done
it hopefully has crashed at some point if there's a bug
contrary to Casey's like the Phil C thing
which is let's instead of having A San just kill it
let's put in like intermediate representation logic
within LVM that says like hey we're going to assign lengths
of things to see arrays such that you are not allowed
to program in memory on safety.
So it's kind of two different schools of thought on like
sanitization versus runtime, if that makes sense.
And for people who don't know,
because like a lot of people probably haven't written,
like systems level code,
like maybe Ed,
you can just give a really brief,
brief overview of like how that memory on safety
leads to bad things happening on someone's computer.
Because I feel like a lot of people,
they just literally don't even know what's going.
on there?
Yeah, 100%.
I mean, so like the crux of every memory exploit boils down to this pattern.
Let's take an array and we want to index into that array using the index I, right?
Now let's, instead of that I being a number that we program into our code statically,
we read I off of the network.
And we're using some type length value network protocol where we have like the type of a field,
the length of a field, and then the number of, or the length of the field, then the
data, right? Most of the time, it just happens that oops, the developer forgot to validate
that I is within the scope of that array, and so you get an arbitrary, read, arbitrary,
right. And that ability to arbitrarily read and write data gives you ASLR bypass. It gives
you stack canary bypass. It gives you the ability to override relocatable, so you can redirect
program control to somewhere else. And that, like, that is the crux of almost 80% of memory
corruption bugs, right? There's some other ones that are a little more weird. So if you literally just
create proper bounds in a language that is memory unsafe that disallow a user to write outside of
their confines that solves the problem. And so Phil C, again, I haven't used it. I haven't explored
too much into it. What I understand is that Phil C uses LVMIR to say like, oh, you've made an array
that is 64 bytes. I'm going to put, you basically turn all arrays into vectors and they do
runtime checks on the vector before you do rights. And like, oh, if you violate that, you can't
continue. And so that
stops most bug classes. I think
Casey was talking. I say it's a little
it's more hardcore than that.
Like Phil C is like kind of
like if you actually, if
you're someone who is 100
percent, you know, at the rust party
ladling out the rust Kool-lade
yeah into into the
little rust cups that you hand out and go like let's do
this, let's drink this guys. Then you
should love Phil C because it takes it
way more seriously even.
So essentially the way that Phil C
is designed to work is it's a lot like the hardware extensions only instead of trying to be
relatively transparent. It's saying, look, we're going to incur a cost. And so what it actually
does is it tracks essentially all allocated objects of any kind. So anytime you actually do
any kind of allocation, it's going to say, all right, I'm going to track that in using, I mean,
what you would call like memory outside of the addressable space of your language, meaning
doing what you're able to do inside a Phil C program,
you cannot access the tracking data, if that makes sense, right?
And so that tracking data will then be used
any time you're trying to work with one of these pointers,
you know, like a regular C pointer.
To you, it looks like you're working with the pointer normally
like you wouldn't see.
But actually, Phil C is going to look to make sure
that that pointer originated
from the actual part of memory that you are accessing, right?
So it tracks not just are you in bounds,
meaning not just are you within the particular object that you,
that you sort of claimed you were accessing,
but are you in the one that this pointer originally came from?
And this works even if you, like, read and write pointers
to, like, blind memory and stuff like this, right?
Because essentially what Phil C is doing
is it's using sort of almost like a super,
It's using a 64-bit value that you don't directly use, you indirectly use it by looking at sort of that backing, that tracking information to make sure that you're tagged, that you like match what you're trying to access.
And so when they do this in hardware, it's a sort of a weaker version of this.
What they do is for pointers in the hardware versions of this, they just use the top bits of the pointer that wouldn't be used because you don't have that much memory.
you don't have 64 bits worth of memory in a machine.
They use the top bits to assign, say, like, a four-bit tag,
a value between 1 and 15, let's say, and 0 is usually reserved, that sort of stuff.
They'll use that tag, and then every block of memory that you sort of allocate,
or rather that you mark, you can say like this region of memory,
you can mark regions of memory with tags, whatever you want,
some random tag that you associate.
Every time you use a pointer to access some memory,
it checks to see whether the tags match.
So that even if two blocks of memory are right next to each other,
if you go from one to the other by increment of the pointer,
like low-level was saying,
if you go outside of like an array bound,
the tags hopefully won't match
because hopefully any two neighboring regions got different tags, right?
But that's really like, there's some other things that you can use
that these extensions do,
but for the most part it's doing that sort of thing.
And Philsey is just sort of like the on steroids version of that, right?
It tracks everything about these so that you can't even have accidental conflicts of the tags.
It's not just using some simple, like, 4-bit scheme.
And it also does, like, more aggressive use after free tracking and all this other sorts of stuff
by using garbage collection to, like, never remove those things so that it remembers, like, each region
until it's actually not accessible by anyone anymore and so on.
So hopefully that's just a little bit, like, that's like, so it's a much more complete system
than something like address sanitizer, if that makes sense.
So that's a lot of stuff in there, but.
Is it effectively turning all memory accesses into like a virtual pointer where like, it's like a look up into another object table and then it does access?
I mean, that's probably not the, that's probably it sounds a little bit more, uh, that might be a slightly more aggressive way to say it.
You can think of it more like, um, there's almost like a shadow version of thing.
Yeah.
You should go take a look.
They have a very nice page that has it just something.
Yeah.
I'll show you, but I have to power up first.
Jesus Christ. Where do you have only
from? Why? Why?
Okay. That's pretty good.
Now I'm Super Scion mode because we have a whiteboard.
Super Say and Rust user. I like it.
Yeah. Okay. So in this case,
right, we have like pointer X. It's pointing to 40.
Right? Y. 4.4. Right.
You can imagine in memory, we've got these two pointers, right?
What happens in normal C when you access like X5?
Yeah, you just get zero or whatever, whatever like the next if element is. Yeah.
We get over here.
Yeah.
But in Phil C, it says, yo, this, if we did like Malik 4 and Malik 4 for both of these, right, in this case,
it's going to say it's got a lower bound, a 4-0, a upper bound, a 4-3.
Yeah.
And here's where it currently is.
Well, I understand that.
I'm working here for the implementation, right?
Like, in the context of this example, what is X?
Is X a pointer to a thing or is X?
To you the user?
Yeah.
The X is just number.
The X to you the user is still just this pointer.
Interesting.
But this is, I'm assuming, this is what I'm going to.
maybe we can get confirmation as far as I could tell from reading and everything else
it gives you back exactly this this is what you think you've got I think it's wider so I don't
think that's how it works it's 16 bytes wide though right no no no no no it's it's the same size
it's 64 bits oh it is okay it's yeah I I don't use Phil C and the first time I heard about
Phil C was when you guys said we were doing an episode about Phil C so I apologize for
not knowing more about it, if I was a Philcy user, I'd be happy to give the flux
patient.
I believe the way that it works is they use a shadow allocation.
So every time you allocate something, they allocate twice that effectively, right?
Yes, you're right.
You're right, Casey.
And then they use, so effectively what X is, is it's going into the shadow region,
which then tells Phil C where, like, how to get the additional date, right?
Data.
In fact, you said the person who wrote it was in chat.
Is that a correct?
Would that be a good summer?
Because I read about this literally yesterday, so that's all I know.
But that, I believe, was how it was explained in the documentation.
Yes.
Yes.
I think you're right, Casey.
Yes.
That was my apologies.
It doesn't return the wider one.
It has one somewhere else that it's holding onto that tells you.
It's called Invisicaps, right?
It has the invisible capabilities stored off in a region in which you're not allowed to access in which the thing returned to you look just like a pointer.
It sounds like a pointer.
And in C, it's just literally a number.
and then boom, bottom, bang, it does the runtime checks against it.
And that's why you can still add to it and work with it like you normally would,
because because they have a shadow region,
they can still figure out what's going on there, right, or things like this.
And so I don't know the specifics.
I want to now read more about it because I thought it was really cool when I was reading.
It was like, oh, this is a really neat thing.
So I'd like to go read about how they handle all the actual practical details,
but I didn't immediately find sort of the document of that.
There's really good overview documents, but like, oh, how did you handle this?
How did you handle that?
Like, I didn't find that immediately.
So I'd like to go read, like, how do you actually use the shadow region?
Like, how is it doing that?
And all that sort of stuff.
And also, the other important thing that they bring up in this documentation, which I think is important to mention as well, is that if a naive implementation of stuff like this would have a lot of problems with threading potentially.
Because, like, different people can sort of mutate pointers and from, you know, and you can have race conditions, this sort of.
stuff. And so Phil C is also also very careful to make sure that they get those things right, which
again, like, if you look at it, it's like, wow, this sounds very complicated. Like, why did it have to,
you know, why does it have to allocate all this extra memory or things like that? And the answer is
because they were, they were trying to take this really seriously. Like, not like, oh, we caught
some memory bugs, but like, no, we really do provide a secure operating model, which is, which again,
if you're drinking the Rust Kool-Aid, you have to respect that. This is, this is doing it
real and on existing programs. It's pretty great.
Yes, we like that. That's the crazy thing for the Russ people.
Even with my Rust super crazy hair on right now, that I don't really get.
It's like, this is good. This stops this from happening.
Right now, if you ran C code and you did this, it would be chill.
You're like it would let it, it would be chill.
It would let you just read from memory. That's not the thing that you're doing.
That's bad. We don't like that. We want computers to work good.
Like, that was the thing that I don't get.
So that part's good.
And it seems like for some reason everyone's mad about it.
And I don't really get why they're mad.
I don't know.
Because it's good.
Most people really hate it when you introduce something good.
That's not the thing that they were previously telling everyone was good.
Right?
Like they don't like to hear that someone else made something good that might be a reason not to use their good thing.
That's true.
Right?
Like heaven forbid, right?
But yeah, there's, I do have.
have one question about Philsey that I wasn't able to answer directly from my sort of like five second read.
So again, like it'd be nice to meet maybe if if if the author is in chat, maybe they can come on sometime and tell us so that they, so that people can have a more accurate description of what it's actually doing because that would be really nice.
And obviously they would not get it wrong because they wrote it.
But what I was going to say is I don't really know how this works with things like,
okay, I create a block of memory that I'm going to sub-allocate out of, and I wasn't sure, like, what it does for that.
Like, that's what one thing that's like on my list now.
I'd like to go read about, like, how it deals with that.
And, like, are there, is that just disallowed?
Is it allowed?
And we just say, oh, well, it doesn't catch problems.
What?
No sub-capabilities right now.
Okay.
I assume that's because if you take a pointer from that region, you technically have a lower bound.
of the original lower and the amount of the big upper.
And so that's a thing that makes it kind of hard to port a lot of existing programs
because a lot of them will do that, right?
And so then it's kind of like, okay, those programs kind of have to be rewritten to,
like maybe there's some way that, you know, Phil C could be extended to support that.
Like, hey, allow us to sort of write a section that's like, here's the,
here's how the memory marking is going to work inside our thing.
I don't know.
But like that would make it challenging to port programs.
that were written in that style, which is a very good style of writing.
Like, it's very efficient.
And so it's kind of, I don't know what you do about that if it's, you know,
in terms of I want to use this in some subset and I want to just use my existing C code.
Effectively, the creator, Piz is saying the best thing you can do with your arena allocators
is to replace them with individual Malix.
Okay.
I mean, which is not that hard because usually your arena allocations are going through
like a pound define
kind of a thing to like allow you to
switch them for debug and stuff like that anyway
or to mark like where they're coming from
and I assume I guess let me ask
another question while we have the benefit for the author in chat
so do you then just
like how do you because normally
arena freeze are just going to free
the whole arena so is that
just taken care of by the garbage collector
then don't call them free
let the GSP deal with it
don't yeah then so
then that's not a hard port
yeah right that's not a that's not a
difficult port, I don't think. For most people, because
at least for my own code, I always
have those running through a macro so you can mark them with file
in line and debug and stuff like that. So that seems
pretty reasonable.
And
if you've been following along, we'll link as well
Pizzlinator, your
X in the, like, description of
the episode. But like,
there's been working on
a bunch of different, like, very
complicated, very real world
C programs that
are big, that you cannot
not just rewrite to Rust.
Guys, you can't do it.
And talking about like EMAX and Ruby and a few other ones,
you can follow along as he's kind of like micro blogging.
As they say, that's in these days, right?
Micro blogging.
I'm on Tumblr, obviously.
You can tell from my hair.
So you can follow along there for a bunch of different ones
and see what he's been up to and how he's gotten there, which is cool.
Cool.
TJ, as the resident Rust expert,
yes, thank you.
Could you help us understand things that Phil C doesn't do?
Or why would you, like if you're starting brand new,
but you're really good at C,
why would you even want to choose Rust if you want to type,
like, or at this level of safety,
and you're like, well, I could just use Phil C, but why would you want to choose Rust?
Yeah, a blue field project, if you will, for me.
Yes, yes.
A blue sky project, T.
Blue sky, a blue sky project.
If I was starting a new blue sky project today, what would I pick?
Okay, so one reason you wouldn't use Phil C.
You don't enjoy writing C.
That's one reason.
That's a legit reason, okay?
There's lots of projects that don't need to be written in C.
Okay?
That's fine.
In fact, there's lots of projects that don't need to be written in Rust.
I almost have to take this off when I say this, right?
It's just true.
You lost your blue hair on that one.
I know, I know.
I get to agree.
I think you're going to have to lose the wig, Teage.
That was, yes.
You've been, yeah, you've been removed from your board seat on the Rust Foundation for that.
But okay.
Yes.
But let's say you're starting out a new project.
And the requirements are such that Rust makes, or some systems language makes a good choice.
Right.
So, or you just have some other requirements.
The example for me that, like when I was working at Sourcegraph, we have a very straightforward
in and out system where we have text come in and we need syntax highlights to come out on the other side.
It actually matters for that to be really fast. You want it to go really fast. It's always going to look the same shape.
You have text come in. You'd like to copy it not so often. You're going to run this for like lots of different files and lots of different languages for lots of different customers.
You'd like this to be really good and really nice and really, really fast. Okay, you have options for what you
could do, right? You could write that service in C, I guess, right? It's maybe a little bit,
it's a little bit harder to picture, but there are like decent like parser generators and other
stuff you could use to get you part of the way there. And then you could apply some like syntax
highlighting from that and all that good stuff. But now if you're going to go and do something with
Phil C, you're going to experience a slowdown. And if you don't do that, you know, you're more
likely to experience some bad security vulnerabilities on a bunch of untrusted input because you're
highlighting random people's code right so oh they put in a unicode character that was too wide for your
thing and then overflow this buffer and now you access this it's corrupted memory and you screwed yourself
over too bad so sad right so uh so in in some cases like this where you need you need a lot of
speed you're maybe going to work on a lot of untrusted input you're connected to the internet you're
doing other stuff like that um like i think there's
good reasons why you might want to choose rust and you'd be able to get like faster performance or
something like that with rust i mean also i think um you know from a like technical standpoint
a lot of people appreciate the some of the like type system guarantees you can get from rust
that filsi is not going to give you you're hopefully now like you won't in uh in many cases
have like an actual security vulnerability you won't have a c vee from these kinds of problems
but it will crash like at runtime, which is good.
That's objectively better.
Also, Rust crashes at runtime for things too.
That's also how it solves some problems.
So that's not like if Rust acts as something outside and it's unchecked,
that's just an expector of panic and then it will crash.
Sweet, that's memory safe.
We are happy.
That's actually good.
But like there's lots of things.
The example you had brought up earlier for like file descriptors, right?
In Rust, if I open up a file and I am making my,
own, you know, like API for it. I'll have the file descriptor, like, or I'll have the function take a
callback. That callbacks, one of the parameters, will be a reference to the file descriptor.
In Rust, the borrow checker will prevent me at compile time from accessing that outside of the
callback, right? So you couldn't like save the file descriptor to a global and then try and read from it
later. That won't, that like won't work, right? And most of the time it's like not clonable. And
not copyable. So you would have to go through like a lot of hoops to try and even get that value
out in a way. You could even literally like just copy it. The callback pattern is impossible in
Rust. It's so hard to use. The callback pattern in Rust, it's so freaking tough.
True. Yes. I still haven't figured out streams quite successfully yet. Yeah. Um,
but that would be a thing, right, that like if I try and use this value, this file descriptor
outside of the callback, the type system and the borrow checker, right, the linear type
system that Rust has will block you from being able to do that at compile time instead of like
runtime, right? That's like for me, I'm a type systems guy like types. For me, that makes me
that makes me happy, right? Like, of course, especially with the blue hair on, that makes me really,
really happy. So that would be something where like if what you want to do, right, like push left,
we're going to push the errors to happen earlier along in the dev cycle. We're going to experience
those at the compiler and there's no like 100,000 lines of battle tested code that has a bunch of
stuff you might choose Rust over like Phil C right and then you like and that would be I think a
reasonable choice but for me that's everyone seems to be talking past each other about that on the
internet which is surprising can I can I ask a clarifying question there I'm not sure I 100%
followed that first of all I would also say that the phrase push left yeah strongly like sort of
suggests a left to right leading language, reading language, because that's the order you're going in.
So I think you lose the blue hair on that one as well. But...
True.
You should say more towards the beginning of a sentence push, is the correct way to say that.
Yeah, exactly.
What I would say is, what is the bug you're trying to prevent with this file handle scenario,
just to I understand what you mean by Rust preventing this better than...
Like, if you have some function, right, that like opens up and then closes a file.
handle for you and says like, hey, or a file descriptor, right?
Or any kind of this thing, database connection, any kind of thing where you have like a handle,
right?
Uh-huh.
Uh, if you're writing this and like, this is not true of just C, but this would be like
in Python or something too, you could just like save that handle inside of your callback to some
global value.
It can escape its region, right?
So if you like do with open file descriptor in Python and then inside of there,
you like save the file descriptor.
And later in your program, after that original thing's already closed it, you're outside of that region now.
You try and read from it again. It'll be an error. It will crash, right?
But I mean, that's pretty easy to implement in C or C++ as well, right?
Like, especially C plus plus.
To do what part?
You just wrap that, wrap file handles in an accessor and that will just work.
Right? So, like, if you wanted that protection in C, you could just get it, right?
Um, like you don't need a language.
Rust being defeated as we speak.
No, I mean, I'm not trying to just on Russ.
I'm just saying, I don't understand why you couldn't just make that same thing by just making
sure that instead of using like an int as your file descriptor, you actually use a struct that
does something, you know, or, you know, a C plus plus class for, yes.
Upjuriant programmers, right, whatever.
But, but I'm saying like sort of regardless of that, I think, I think we're not,
we're not talking about the thing.
I'm saying, like, we could prevent in, like, rust from the,
with the borrow checker, you can prevent the value from escaping its region, right?
Which I don't, which I, maybe there is a C plus.
I'm sure there is a C++ thing that can do that.
I don't know.
I just assume everything is possible.
You're just talking about like, you want, like, because they have special cased file descriptors
with the static analysis in Rust or something like this.
Yeah, I think I'm, I'm saying.
You're talking about type system and I'm like, well, the type system in both can do what you're
talking about.
So we're just talking about the type system as opposed to other things.
Right?
Yes.
I'm,
I'm just talking about the kinds of things.
Like,
this is,
you know,
as like,
I'm trying to present the case for why someone would say they would
rather write this kind of thing in Rust,
right?
Is instead of experiencing a crash with Phil C at runtime,
okay.
We could find that out from the compiler.
Right?
That,
like,
oh, this kind of access isn't allowed.
That's not thread safe.
That's not,
that escaped its region,
but it shouldn't.
This kind of value,
right?
Like there are things that we can do there, right, in like Rust with the type system that fight the same kinds of bugs you might get, you might get solved from Phil C.
Right.
But instead of having a crash at runtime, we get, it doesn't compile and I handle that case.
Yeah, the borrow checker defeats use after free and double free at compile time.
That is the objective of the borrow checker.
Yes.
That's a probably way more succinct way to say that.
Good job, Ed.
I like to think of it as just like it's effectively a unique pointer, but at compile time.
Right.
So my point being, separately from, I think it's obviously good that there's an option where we can solve a bunch of these classes, classes of bugs in C and prevent it, right?
In this case of like which language would I pick for certain projects, there are definitely like reasons you would pick rust over just picking Phil C.
for like a new greenfield project.
Of course, there's other reasons why you might pick C over Rust as well.
Like, you might actually ship it and things like that, which is cool.
So, but that's like those kinds of bugs, Phil C does not solve that at compile time.
That's all I'm trying to say as like a comparison of the two.
And that's like a reasonable tradeoff that people want to make.
Yes.
And that's also that's where you get the performance from.
That's because of the barrow checker, not the type system, right?
just so we're clear on that part, right?
I mean...
Or just so I'm understanding it, I should say, right?
Because that was the part that threw me,
I was like, why is that a type system problem?
Okay.
Technically, actually...
Okay, so it is actually the type system.
Well, the borrow checker is sort of like a result
of the linear affine type system that Rust has.
Okay.
And so...
I would too dumb in this conversation.
I don't know what's going on.
I would just say they go together.
You would, like...
Right, so you're talking about type system,
the type system being like,
including the borrow checker.
Yes.
Okay, gotcha.
Yes, exactly.
That makes sense.
So I also have another question, which is that does Rust catch all of the same memory errors that Phil C does?
Because I don't know if that's true.
No.
Phil C. might catch more.
It does.
Yeah.
That's the best part.
If you really care about security, you probably shouldn't be using Rust.
Yeah.
Russ will catch them, but it'll turn the condition into a DOS.
So it's like, it's not an exploitable memory access, but it's also not caught a compile time.
So like, you can do that.
I mean even at runtime,
does Phil C catch things that Rust doesn't catch, is my question.
At run time?
I thought I saw a condition.
I unfortunately forgot to save it,
but it's a condition in which Phil C does not catch something in which Rust does.
I really wish I would have.
Unsaf blocks, there are, I think, certain things you can do
that in Rust, inside of unsafe blocks,
that Rust does not check.
Real quick.
Even all of its stuff.
And maybe still, I'm not actually 100% sure if it will do a CVE.
But inside of unsafe box, that Phil C does catch.
I do it.
I do have to go in five minutes.
I have a question for the off.
Memory safety issues.
Yes, Phil Ed.
Sis call related memory safety issues.
Are you saying, for example, in a cis call handler where it does a copy to user,
like outside of the bounds of a memory region?
Like what about cis calls in particular?
I'm curious what you're saying there.
And then I do have to run.
I'm sorry, guys.
I just want to say he said he did confirm CVN unsafe blocks is totally possible.
He said yes.
Okay, how would Phil C detect that?
Yes, Piz.
Give us the, give us the nine yards.
And then we'll have to just have Phil come on.
Yeah, 100%.
I'm so curious.
The right thing is to have him on the show.
If he, if song as he wants to come on, I mean.
He said yes.
Okay, great.
Yes.
Yes.
Yes.
There's also, I do think, can I just mention what other thing as the Russ person?
I'll just put this back on.
Oh.
Sometimes 20% slower or up to four times and 1.5 to 2 times as much memory actually makes it not possible to do.
Constrain hardware or like other stuff like that.
We'll just literally make it so it's just not possible to accept the performance hits because some places in the world, performance still actually matters and you can't just spin up 5,000 new lambdas and pay $10 million in cloud costs.
Okay, there you go.
You're just summit.
You're going to summon DHS, dude.
You're going to summon him.
He's going to be like, yes, we can. He's like, yes, we can. We will spin up all of them.
No, he's against that. It's also true. You've got to be careful. You can technically spin up all of them. You just pay a lot of money.
This is blowing my mind right now. He said that it intercepts all cis calls of the ABI layer, which makes sense.
Phil, I know what we need. We need a slideshow with these examples, and we can work on it together. I'll message you after this on X, and we'll get the set up.
We'll come back with a slideshow with code examples, and then, Ed, you can ask every single question you want.
I've been wanting to do this a lot.
Ever since trashed the, the TypeScript presentation,
I've been wanting to do more presentations
and then have us all interrupt the presentation
to be like, but what about this?
What about this?
What about this?
And that was such a fun time.
Yes.
All right.
Well, then let's end it right now.
Low level is going to take a question.
I have to say one quick thing.
Oh, go ahead, Brian.
I will say that every time I use a union and see,
I get so happy and so sad at the same time
because it does make me long and yearn for rust.
I will say that the automatic tagged unions
at the syntax level is just a thing of glory and beauty 100% of the time.
But don't worry, in another 50 years, the C++ committee will finally get one working.
We're almost there, guys.
One more committee.
One more version.
One more 2,000-page revision, and they'll get the discriminated unions working properly instead of sucking.
Casey, if that were true, then why are some people using, like, C-17 instead of C-94?
That doesn't even make sense, then.
It doesn't make sense.
Go, checkmate.
Because 94 is bigger than 17, so we should be using that one, don't you think?
2020, 2094.
I got to go.
Bye.
Sounds worse then, really.
All right, everybody will go as well just because this is happening and already left us and now the stream is completely screwed up.
Thank you, everybody, for joining us for this.
Hey, if you are watching on YouTube, you can see everything on Spotify.
You get the full episode because you miss a lot of the banter when you only watch it on YouTube.
So thank you very much for watching.
Thank you for all the guests.
Ed with low level.
Dot Academy,
Casey with Computer Enhanced.com,
and Teage with boot.
Dot dev slash Teage.
Or by the way.
Or by the way,
if you want to support both T.J.
and I,
because I also have two courses on there as well.
I just did like a Spider-Man thing.
And the name is the Spiteagen.
All right.
Thank you, everybody.
Boot up the day.
Vibe coding errors on my screen.
Terminal coffee
And here
