Prev: GDAL-1.7.1 : vcvarsall.bat missing
Next: improving python performance by extension module (64bit)
From: Kushal Kumaran on 29 Jun 2010 00:19 On Tue, Jun 29, 2010 at 5:56 AM, Lawrence D'Oliveiro <ldo(a)geek-central.gen.new_zealand> wrote: > In message <mailman.2231.1277700501.32709.python-list(a)python.org>, Kushal > Kumaran wrote: > >> On Sun, Jun 27, 2010 at 5:16 PM, Lawrence D'Oliveiro >> <ldo(a)geek-central.gen.new_zealand> wrote: >> >>>In message <mailman.2184.1277626565.32709.python-list(a)python.org>, Kushal >>> Kumaran wrote: >>> >>>> On Sun, Jun 27, 2010 at 9:47 AM, Lawrence D'Oliveiro >>>> <ldo(a)geek-central.gen.new_zealand> wrote: >>>> >>>>> A long while ago I came up with this macro: >>>>> >>>>> #define Descr(v) &v, sizeof v >>>>> >>>>> making the correct version of the above become >>>>> >>>>> snprintf(Descr(buf), foo); >>>> >>>> Not quite right. Â If buf is a char array, as suggested by the use of >>>> sizeof, then you're not passing a char* to snprintf. >>> >>> What am I passing, then? >> >> Here's what gcc tells me (I declared buf as char buf[512]): >> sprintf.c:8: warning: passing argument 1 of âsnprintfâ from >> incompatible pointer type >> /usr/include/stdio.h:363: note: expected âchar * __restrict__â but >> argument is of type âchar (*)[512]â >> >> You just need to lose the & from the macro. > > Why does this work, then: > > ldo(a)theon:hack> cat test.c > #include <stdio.h> > > int main(int argc, char ** argv) > Â { > Â Â char buf[512]; > Â Â const int a = 2, b = 3; > Â Â snprintf(&buf, sizeof buf, "%d + %d = %d\n", a, b, a + b); > Â Â fprintf(stdout, buf); > Â Â return > Â Â Â Â 0; > Â } /*main*/ > ldo(a)theon:hack> ./test > 2 + 3 = 5 > By accident. I hope your compiler warned you about your snprintf call. Reading these threads might help you understand how char* and char (*)[512] are different: http://groups.google.com/group/comp.lang.c++/browse_thread/thread/24708a9204061ce/848ceaf5ec774d81 http://groups.google.com/group/comp.lang.c.moderated/browse_thread/thread/fe264c550947a2e5/32b330cdf8aba3d6 -- regards, kushal
From: Mark Lawrence on 29 Jun 2010 10:31 On 29/06/2010 01:55, Roy Smith wrote: [snips] > The nice thing about null-terminated strings is how portable they have > been over various word lengths. The bad thing about null-terminated strings is the number of off-by-one errors they've helped to create. I obviously have never created an off-by-one error myself. :) Kindest regards. Mark Lawrence.
From: Lawrence D'Oliveiro on 29 Jun 2010 20:25 In message <mailman.2332.1277785175.32709.python-list(a)python.org>, Kushal Kumaran wrote: > On Tue, Jun 29, 2010 at 5:56 AM, Lawrence D'Oliveiro > <ldo(a)geek-central.gen.new_zealand> wrote: > >> Why does this work, then: >> >> ldo(a)theon:hack> cat test.c >> #include <stdio.h> >> >> int main(int argc, char ** argv) >> { >> char buf[512]; >> const int a = 2, b = 3; >> snprintf(&buf, sizeof buf, "%d + %d = %d\n", a, b, a + b); >> fprintf(stdout, buf); >> return >> 0; >> } /*main*/ >> ldo(a)theon:hack> ./test >> 2 + 3 = 5 > > By accident. I have yet to find an architecture or C compiler where it DOESN'T work. Feel free to try and prove me wrong.
From: Lawrence D'Oliveiro on 29 Jun 2010 20:26 In message <slrni2f8v2.j19.grahn+nntp(a)frailea.sa.invalid>, Jorgen Grahn wrote: > On Sat, 2010-06-26, Lawrence D'Oliveiro wrote: > >> In message <slrni297ec.1m5.grahn+nntp(a)frailea.sa.invalid>, Jorgen Grahn >> wrote: >> >>> I thought it was well-known that the solution is *not* to try to >>> sanitize the input -- it's to switch to an interface which doesn't >>> involve generating an intermediate executable. In the Python example, >>> that would be something like os.popen2(['zcat', '-f', '--', untrusted]). >> >> That's what I mean. Why do people consider input sanitization so hard? > > I'm not sure you understood me correctly, because I advocate > *not* doing input sanitization. Hard or not -- I don't want to know, > because I don't want to do it. But no-one has yet managed to come up with an alternative that involves less work.
From: Michael Torrie on 30 Jun 2010 00:05
On 06/29/2010 06:25 PM, Lawrence D'Oliveiro wrote: > I have yet to find an architecture or C compiler where it DOESN'T work. > > Feel free to try and prove me wrong. Okay, I will. Your code passes a char** when a char* is expected. Every compiler I know of will give you a *warning*. Mistaking char*, char**, and char[] is a common mistake that almost every C program makes in the beginning. Now for the proof: Consider this variation where I use a dynamically allocated buffer instead of static: #include <stdio.h> int main(int argc, char ** argv) { char *buf = malloc(512 * sizeof(char)); const int a = 2, b = 3; snprintf(&buf, sizeof buf, "%d + %d = %d\n", a, b, a + b); fprintf(stdout, buf); free(buf); return 0; } /*main*/ On my machine, an immediate segfault (stack overrun). Your code only works because your buf is statically allocated, which means &buf==buf. But this equivalance does not hold for any other situation. If your buffer was dynamically allocated on the heap, instead of passing a pointer to the buffer (which *is* what buf itself is), you are passing a pointer to the pointer, which is where buf is stored on the stack, but not the buffer itself. Instant stack corruption. |