Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get back to sel_getUid()'s original behaviour

TL;DR: How does one check that selector with given name was registered, without actually registering it?

Thanks!


Hi, I have an Objective-C application and bunch of NSObjects that are exported into Lua state via simple proxy library written in objc. All Lua-side calls like these:

exported_objc_object:myMethodName(...)

-- same as --
exported_objc_object.myMethodName(exported_objc_object, ...)

-- same as --
key = 'myMethodName'
exported_objc_object[key](exported_objc_object, ...)

are forwarded as if someone called:

[objc_object lua_myMethodName:L];

// declared as
- (int)lua_myMethodName:(lua_State *)L { ... }

Actually, any 'get' opcode on Lua-exported object returns a cached Lua-closure that on invocation will call corresponding Objective-C method via selector constructed with sprintf(s, "lua_%s:", key)) && sel_getUid(s) (all checks included). If produced selector is not implemented in terms of -[respondsToSelector:], then exported_objc_object.myMethodName simply returns nil.

Obviously, proxy library has to make dynamic lookups via sel_getUid() or sel_registerName() (I believe both @selector and NSSelectorFromString() also end up there). The manual states that sel_getUid() was intended to lookup selector names (as opposed to immediately registering them into SEL registry), but it's modern implementation now does the same as sel_registerName() due to bugs in someone's teh codez back then.

I can just stick with sel_registerName() behavior, but that leaves memory-eating attack vector, as some malicious script may start looking up long random/invalid selectors via sml object[makeRandomKey()] in a loop, thus overflowing SEL registry forever. If sel_getUid() worked as planned, proxy lib would be able to test selector presence and only then actually check if object responds to it, without excessive registering. But it doesn't.

like image 449
user3125367 Avatar asked Sep 29 '22 07:09

user3125367


1 Answers

Here is a hack that might work, that uses the implementation-dependent fact that a selector is a C string.

sel_isMapped((SEL)(void *)"lua_myMethodName:")
like image 112
newacct Avatar answered Oct 17 '22 20:10

newacct