You even put the correct comment there but wrong index!?
> lua_setiuservalue( L, -1 /* must be -2 */, 1 );
(The second argument is the index of the userdata not the upvalue.)
For explanation why 'lua_setiuservalue' returns 0 read below.
In your case, what happens is that the string value,
which is also an object is being casted to userdata.
And then you are accessing the 'nuvalue':
```
typedef struct Udata {
CommonHeader;
unsigned short nuvalue; /* number of user values */
...
other fields
...
UValue uv[1]; /* user values */
} Udata;
```
Here is the string object:
```
typedef struct TString {
CommonHeader;
lu_byte extra; /* reserved words for short strings; "has hash" for longs */
ls_byte shrlen; /* length for short strings, negative for long strings */
...
other fields
...
char contents[1]; /* string body starts here */
} TString;
```
As you can see, you are casting a string as userdata and by taking 'nuvalue' you
are instead taking ('extra' | 'shrlen'). The following check will fail in
cases where your URL is an empty string or a long string (more than
LUAI_MAXSHORTLEN which is 40 bytes).
```
if (!(cast_uint(n) - 1u < cast_uint(uvalue(o)->nuvalue)))
res = 0; /* 'n' not in [1, uvalue(o)->nuvalue] */
else {
setobj(L, &uvalue(o)->uv[n - 1].uv, s2v(L->top.p - 1));
luaC_barrierback(L, gcvalue(o), s2v(L->top.p - 1));
res = 1;
}
```
So this is why 'lua_setiuservalue' returns 0. If the URL string is not an
empty string but less than 41 bytes, then you will break things as you
are executing the 'else' branch.
I am curious, are you passing different kinds of URL strings, or you are just
testing one URL and the function keeps returning 0?
--
Jure