[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: [hack] nil.foo = nil
- From: Sean Conner <sean@...>
- Date: Thu, 1 May 2014 22:34:54 -0400
It was thus said that the Great Andrew Starks once stated:
> On Thursday, May 1, 2014, Thiago L. <fakedme@gmail.com> wrote:
>
> > NIL_VALUE = {}
> > softmt = { __index = function(t,k) if rawget(t,k) == nil then return
> > NIL_VALUE else return rawget(t,k) end end }
> > setmetatable(NIL_VALUE,softmt)
> >
> > softtable = {}
> > setmetatable(softtable,softmt)
> >
> > val = softtable.some.invalid.key
> > if val == NIL_VALUE then return "it works!" end
> >
> > Best part? If you don't have a __metatable protected metatable:
> >
> > oldmt = getmetatable(t)
> > setmetatable(t,softmt)
> > val = t.insert.some.long.chain.here
> > if val == NIL_VALUE then val = nil end
> > setmetatable(t,oldmt)
> > -- etc
> >
> > While it's not as nice as Groovy[1] it does the job just fine...
> >
> > [1] http://groovy.codehaus.org/Null+Object+Pattern
>
> The thing is, this hack works with every table in existence, not just ones
> that don't have an __index method that is available for override.
>
> The trouble(?) is, it works with nothing, too:
>
> local foo = nil
>
> print(foo.bar)
> --> nil
>
> It kind of breaks my brain. I'm not near a real computer, so I'll have to
> try out what happens when a table with __index assigned to a table returns
> nil... Does the rawget kill the fun? It might not... Probably need more
> sleep to hypothesize. :)
Okay, try this out (Linux only):
#define _GNU_SOURCE
#include <sys/mman.h>
#include <stdio.h>
int main() {
int *ptr = NULL;
if (mmap(0, 4096, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0)
== MAP_FAILED) {
perror("Unable to mmap(NULL)");
fprintf(stderr, "Is /proc/sys/vm/mmap_min_addr non-zero?\n");
return 1;
}
printf("Dereferencing my NULL pointer yields: %d\n", *ptr);
*ptr = 17;
printf("Now it's: %d\n", *ptr);
return 0;
}
Now, ask yourself---self, is this a Good Thing(TM)?
-spc (It's too bad you can't mmap() a page read-only, and mmap() a
different page at the same address write-only [1])
[1] Or is it a Good Thing(TM) that you can't do that?