generic image
Processing...
  • Games
  • Catalog
  • Develop
  • Robux
  • Search in Players
  • Search in Games
  • Search in Catalog
  • Search in Groups
  • Search in Library
  • Log In
  • Sign Up
  • Games
  • Catalog
  • Develop
  • Robux
   
ROBLOX Forum » Game Creation and Development » Scripters
Home Search
 

Re: upvalue challenge

Previous Thread :: Next Thread 
Ozzypig is not online. Ozzypig
Joined: 27 Mar 2008
Total Posts: 4906
31 Mar 2012 07:21 PM
Write a function that, when given a function, will return a boolean value that represents whether or not the given function has upvalues.
Report Abuse
KingBoo is not online. KingBoo
Joined: 16 Jul 2007
Total Posts: 8495
31 Mar 2012 07:40 PM
function x()
return false
end

lololol
Report Abuse
xSIXxStorage is not online. xSIXxStorage
Joined: 22 Aug 2010
Total Posts: 1811
31 Mar 2012 07:44 PM
^
Report Abuse
MrNicNac is not online. MrNicNac
Joined: 29 Aug 2008
Total Posts: 26567
31 Mar 2012 07:54 PM
I have no way of testing the following, and it's clearly skeptical.

function hasUpvalues(xFunction)
return #getfenv(xFunction)>0
end
Report Abuse
oysi92 is not online. oysi92
Joined: 20 Nov 2008
Total Posts: 361
31 Mar 2012 08:01 PM
@MrNicNac
Upvalues are local variables and parameters. And getfenv only gives a table containing the global variables of the script. So, that wouldn't work.


@Ozzypig
I'm 100% certain you have to use string.dump to do this. If only I knew Lua Assembly...
Report Abuse
nate890 is not online. nate890
Joined: 22 Nov 2008
Total Posts: 21686
31 Mar 2012 08:32 PM
Only way to do this is knowing LASM, as oysi stated in his last post. Once you decode what string.dump returns, you would then parse the source looking for the "local" keyword.
Report Abuse
Anaminus is not online. Anaminus
Top 100 Poster
Joined: 29 Nov 2006
Total Posts: 5945
31 Mar 2012 08:41 PM
I believe the location of the number of upvalues for a dumped function in the dumped string would be the following:

12 + 4 + name + 4 + 4

Where `name` is the length of the source name. You can get that from bytes 13 to 16 in the dumped string (which represents a 4-byte integer). I'm going to cheat a bit and just use byte 13 because the source name generally doesn't go over 255 characters anyway.

function GetNumUpvalues(func)
local source = string.dump(func)
local name = string.byte(source:sub(13))
local up = 12 + 4 + name + 4 + 4
return string.byte(source:sub(up,up))
end


Also, I have no idea if this is right.
Report Abuse
Wizard2268 is not online. Wizard2268
Joined: 31 Mar 2011
Total Posts: 985
31 Mar 2012 08:47 PM
@Anaminus. o.e
Report Abuse
NecroBumpist is not online. NecroBumpist
Joined: 12 Sep 2010
Total Posts: 4198
31 Mar 2012 09:47 PM
@Anaminus:
Yours does not work.

    local a, b, c, d, e, f, g;
    local func = function() print(a, b, c, d, e, f, g); end;
    print(GetNumUpvalues(func)); --> 0

For several reasons:
1.) The name field is Null terminated when it's length is ​> 0, otherwise nothing follow.
Note: unlike string constants, the Null terminator is not included in the integer size of the string.

2.) You missed an integer most likely somewhere (not sure which) because the upvalue offset is 4 (excluding previous null terminator thing) bytes further along

3.) I've seen roblox embed the entire source of a script into the name field of a bytecode dump. Reading the full dword integer isn't hard.

Also, you missed the part of the OP where it said "return a boolean value that represents whether or not the given function has upvalues."
Though I encorporated your idea of just returning the number of upvalues instead as well.


Here's a working implementation:

    function has_upvalues(func)
        local dump = ("").dump(func); -- pretty nice, eh?
        local bytes = {dump:byte(13, 16)}; -- get integer size of the name string
        local name_len = bytes[1] + bytes[2]*0xFF + bytes[3]*0xFFFF + bytes[4]*0xFFFFFF; -- decode the integer
        local upvalue_position = 28 + (name_len ​> 0 and 1 or 0) + name_len;
        local number_upvalues = dump:byte(upvalue_position); -- return the number of upvalues
        return number_upvalues ​> 0, number_upvalues;
    end

Usage/Proof:

    local a, b, c;
    local func1 = function() print(); end;
    local func2 = function() print(a, b); end;
    local func3 = function() print(a, b, c); end;
    
    print(has_upvalues(func1)); --> false, 0
    print(has_upvalues(func2)); --> true, 2
    print(has_upvalues(func3)); --> true, 3
Report Abuse
miloguy is not online. miloguy
Joined: 19 Dec 2009
Total Posts: 7702
31 Mar 2012 10:14 PM
function n(f)
for i,v in pairs(f) do
return true
end
return false
end



I'm not exactly sure what upvalues are. Looking that up now
Report Abuse
miloguy is not online. miloguy
Joined: 19 Dec 2009
Total Posts: 7702
31 Mar 2012 10:17 PM
Oh.

Yeah, I had the wrong idea entirely ._.
Report Abuse
nate890 is not online. nate890
Joined: 22 Nov 2008
Total Posts: 21686
01 Apr 2012 12:08 AM
Miloguy, upvalues are local variables.
Report Abuse
Ozzypig is not online. Ozzypig
Joined: 27 Mar 2008
Total Posts: 4906
01 Apr 2012 12:25 AM
Oh okay then. Bonus points for returning the exact number of upvalues.
Report Abuse
Anaminus is not online. Anaminus
Top 100 Poster
Joined: 29 Nov 2006
Total Posts: 5945
01 Apr 2012 02:08 AM
"2.) You missed an integer most likely somewhere (not sure which) because the upvalue offset is 4 (excluding previous null terminator thing) bytes further along"

That doesn't seem to be right. I was only off by 1 because I didn't compensate for the null byte (seems the source I learned from was wrong). I didn't miss any integers, so the offset should be 24, not 28.
Report Abuse
NecroBumpist is not online. NecroBumpist
Joined: 12 Sep 2010
Total Posts: 4198
01 Apr 2012 09:24 AM
@Anaminus:

Huh, does my example work on your computer? Lua bytecode is terribly platform dependent.
Report Abuse
Anaminus is not online. Anaminus
Top 100 Poster
Joined: 29 Nov 2006
Total Posts: 5945
01 Apr 2012 01:11 PM
No, it doesn't. Maybe it's because we've been assuming that the header info has been the same. Here's your function modified to check the size of ints and string size. It gives the right results for me. Does it work for you?

function has_upvalues(func)
local dump = ("").dump(func); -- pretty nice, eh?
local int_len,size_t_len = dump:byte(8,9)
local bytes = {dump:byte(13, 12+size_t_len)}; -- get integer size of the name string
local name_len = bytes[1]
for i=2,#bytes do -- decode the integer
name_len = name_len + bytes[i]*(256^(i-1)-1)
end
local upvalue_position = 12 + size_t_len + (name_len > 0 and 1 or 0) + name_len + int_len + int_len;
local number_upvalues = dump:byte(upvalue_position); -- return the number of upvalues
return number_upvalues > 0, number_upvalues;
end
Report Abuse
NecroBumpist is not online. NecroBumpist
Joined: 12 Sep 2010
Total Posts: 4198
02 Apr 2012 04:55 PM
Yeah that works.

Curse you Lua and your inability to produce cross platform bytecode!

Report Abuse
Previous Thread :: Next Thread 
Page 1 of 1
 
 
ROBLOX Forum » Game Creation and Development » Scripters
   
 
   
  • About Us
  • Jobs
  • Blog
  • Parents
  • Help
  • Terms
  • Privacy

©2017 Roblox Corporation. Roblox, the Roblox logo, Robux, Bloxy, and Powering Imagination are among our registered and unregistered trademarks in the U.S. and other countries.



Progress
Starting Roblox...
Connecting to Players...
R R

Roblox is now loading. Get ready to play!

R R

You're moments away from getting into the game!

Click here for help

Check Remember my choice and click Launch Application in the dialog box above to join games faster in the future!

Gameplay sponsored by:
Loading 0% - Starting game...
Get more with Builders Club! Join Builders Club
Choose Your Avatar
I have an account
generic image