|
Message-ID: <20110803225357.GC132@brightrain.aerifal.cx> Date: Wed, 3 Aug 2011 18:53:57 -0400 From: Rich Felker <dalias@...ifal.cx> To: musl@...ts.openwall.com Subject: Re: cluts weekly reports On Wed, Aug 03, 2011 at 11:59:52PM +0200, Luka Marčetić wrote: > [ > { > "include" : "stdlib.h", > "function": "char *realpath(const char *restrict file_name, char *restrict resolved_name);", > "data" : [ > { > "file_name": ["\".\"", "\"./123456789\""], > "resolved_name": "NULL", > > "return": "NULL", > "errno" : "ENAMETOOLONG" > } > ] > } > ] OK, I'm imagining something like this: void test_realpath(const struct test *test, void *res, char *buf, size_t len) { *(char *)res = realpath(test->arg[0].ptr, buf); } struct test tests[] = { { .function = test_realpath, .arg[0].ptr = ".", ... }, { .function = test_realpath, .arg[0].ptr = "./123456789", ... }, ...}; With some extra fields to indicate the return type and how the caller should validate the result. Actually I would make a function (called do_test or something) that would do all that work. Note that here I hard-coded the fact that tests will take a buffer/length pair (despite the fact that realpath ignores the length), but you could just as easily have encapsulated the args that the caller might vary into a separate void * argument to test_xxxxxxx() (which it would know how to cast back and extract data from. The result handling could also be better. Actually you might want to consider having the test structure include a "validate" function pointer that would be used to validate the results. A couple reusable validator functions would be one that strcmp's the contents of a buffer (and checks for overwrite at the end), one that compares an integer or floating point result stored at the result pointer, etc.. In addition, the generic code could always check errno unless you have a flag not to check it, or you could make a system where you provide an *array* of validator functions to choose the ones you want, thereby being able to include an errno check and something else. This is all very general stuff I whipped up in 30 minutes or so. I could elaborate on it if this isn't giving you enough ideas. Also, if you think this isn't helpful, please expand on the example you sent me. Seeing ONE TEST doesn't give me any idea of the type of generality you're trying to achieve. Also.. > for (f=0; f<sizeof(t)/sizeof(t[0]); ++f) { > memset(&error, 0, sizeof(error)); > sigaction(SIGSEGV, &act, &oldact); > sig = 0; > for (d=0; !(sig = setjmp(env)) && !memcmp(&error, &no_error, sizeof(error)) && d<t[f].ndata; ++d) { > arg = t[f].data[d].arg; //shorthand args > for (i=0; !memcmp(&error, &no_error, sizeof(error)) && i<iters(t[f],d); ++i) { > switch (f) { > case 0: > if ((ret.s = realpath(ARGV(char *, 0), ARGV(char *, 1))) != *(char **)t[f].data[d].ret) { This is certainly wrong, in general. You can't use equality operators to compare strings, but perhaps you're just looking for null pointers here? Also the second arg needs to be a caller-provided buffer, but part of the test structure, I think.. I'm a bit confused how this code is supposed to work. Rich
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.