Re: Cracking complex C structures

Bob Novas (rgn@cen.com)
3 Jan 1995 13:45:34 GMT

>>>>> "Bob" == Bob Novas <rgn@cen.com> writes:

Bob> 2) The XmTextVerifyCallbackStruct also has an interesting Boolean
Bob> field called doit, which I'd like, on occasion, to clear from
Bob> my python callback. How do I do that, and get the modified
Bob> structure back to X? What I need to do is dereference the
Bob> raw value (the id?) of the call_data argument, offset by a
Bob> suitable amount, and jam a 0.

Well, my solution is a hack, but, given that Xtmodule.c/univ_callback simply
copyies an arbitrary-sized chunk of memory (sizeof(XEvent) + sizeof(int))
starting at the real calldata address as the calldata argument to a python
callback, I extended the chunk by 4 bytes, and tacked the real address of
the original calldata structure to the end of the calldata string.
Then, I wrote a StuffByte() routine that can stuff a byte at an offset
from this address.

I modified univ_callback as follows:

univ_callback(w, closure, call_data)
Widget w;
XtPointer closure;
XtPointer call_data;
{
object *cbfunc;
object *cbarg;
widgetobject *wobj;
object *warg;
object *cbargs;
object *result;
int nbytes;
if (!getargs((object*)closure, "(OOi)", &cbfunc, &cbarg, &nbytes)) {
if (jump_flag)
longjmp(jump_where, 1);
fprintf(stderr, "--- bad closure for univ_callback ---\n");
print_error();
fprintf(stderr, "---\n");
return;
}
wobj = newwidgetobject(w, widget_methodlists);
warg = newsizedstringobject(call_data, nbytes);
#ifndef RGN_ORIGINAL
/*
* tbd - hacked to add the value of the real call_data
* after the end of the call_data string object
*/
if (resizestring(&warg, nbytes+4) == 0)
{
memcpy(((stringobject *)warg)->ob_sval+nbytes, &call_data, 4);
}
#endif
cbargs = mkvalue("(OOO)", wobj, cbarg, warg);
XDECREF(wobj);
XDECREF(warg);
if (cbargs == NULL)
result = NULL;
else {
result = call_object_save_jump(cbfunc, cbargs);
DECREF(cbargs);
}
if (result == NULL) {
if (jump_flag)
longjmp(jump_where, 1);
fprintf(stderr, "--- callback failed ---\n");
print_error();
fprintf(stderr, "---\n");
}
else
DECREF(result);
}

And, added the routines:

static object *
StuffByte(object *self, object *args)
{
object *ob;
char *ptr;
int o;
int v;
int i;

if (!getargs(args, "(lii)", &ptr, &o, &v))
{
return NULL;
}

*(ptr+o) = v;

INCREF(None);
return(None);
}

Ptr2StrObj(object *self, object *args)
{
char *s;
int l;

if (!getargs(args, "(li)", &s, &l))
{
return NULL;
}
return newsizedstringobject((char *)s, l);
}

Now, from python, in an XmText modifyVerify callback, I can clear the
doit flag in the real XmTextVerifyCallbackStruct:

def ModVerCallback(self, VT_obj, call_data):
text = Xm.TextGetString(self)
dict_call_data = Struct.TextModifyVerifyCallData(call_data)
text_block = dict_call_data.textBlock
dict_txt_blk = Struct.TextBlkRec(text_block)
char = Xxx.Ptr2StrObj(dict_txt_blk.ptr, 1)
text = text + char
if (not VT_obj.IsValidText(text)):
# -------------------------------------------------------
# clear the doit flag
# -------------------------------------------------------
orig_call_data_str = call_data[len(call_data)-4:]
orig_call_data_tuple = struct.unpack("l", orig_call_data_str)
offset = struct.calcsize('il')
Xxx.StuffByte(orig_call_data_tuple[0], offset, 0)