{"thread":{"id":"3641","subject":"Re: [PATCH] Trivial warning fix for imap-send.c","startedAt":"2006-03-13T04:12:31Z","lastAt":"2006-12-05T17:34:11Z","messageCount":5,"participants":["Horst von Brand","Linus Torvalds","Jeff King","Horst H. von Brand"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"17521","messageId":"200603130412.k2D4CW1b011631@laptop11.inf.utfsm.cl","threadId":"3641","inReplyTo":"peff@peff.net","subject":"Re: [PATCH] Use explicit pointers for execl...() sentinels.","fromName":"Horst von Brand","fromEmail":"vonbrand@inf.utfsm.cl","sentAt":"2006-03-13T04:12:31Z","receivedAt":"2006-03-13T04:12:31Z","isPatch":true,"sender":{"key":"vonbrand@inf.utfsm.cl","avatar":"https://avatars.githubusercontent.com/u/211384?v=4"},"body":"Jeff King <peff@peff.net> wrote:\n> On Sun, Mar 12, 2006 at 08:08:12PM +0200, Timo Hirvonen wrote:\n> > NULL pointer does not point to any data, it just says it's 'empty'.  So\n> > it doesn't need to be same type pointer as specified in the function\n> > prototype.  Pointers are just addresses, it doesn't matter from to code\n> > generation point of view whether it is (char *)0 or (void *)0.\n\n> Sorry, but I think you're wrong according to the C standard. Pointers of \n> different types do NOT have to share the same representation (e.g.,\n> there have been some platforms where char* and int* were different\n> sizes). A void pointer must be capable of representing any type of\n> pointer (for example, holding the largest possible type). However, if\n> sizeof(void *) == 8 and sizeof(char *) == 4,\n\nVery improbable, they'll be the same normally (\"void *\" is a way of getting\nrid of the overloading of the meaning of \"char *\" for this before ANSI C).\nSure, sizeof(int *) might be 4, but I think that is pretty far off.\n\n>                                              you have a problem with\n> variadic functions which are expecting to pull 4 byte off the stack. \n\nThere are special rules for variadic functions, probably pointers would be\ncast to/from void * in such a case by the compiler.\n\n> In a non-variadic function, the compiler would do the right implicit\n> casting. In a variadic function, it can't. \n\nIt sure can. The rules where defined so that it works.\n\n> The real question is, does git want to care about portability to such\n> platforms.\n\nBroken platform, on which the compiler fails miserably in doing its job?\nNo, it doesn't.\n\n> If you remain unconvinced, I can try to find chapter and verse of the\n> standard.\n\nPlease do.\n\n> > sizeof(unsigned long) is sizeof(void *) in real world.\n\n> Are you saying that because it encompasses all of the platforms you've\n> worked on, or do you have some evidence that it is largely the case? It\n> certainly isn't guaranteed by the C standard.\n\nMore because a machine with pointers that are much larger than the largest\n\"normal\" integer would be pretty weird (sure, on intel 8086 they where 32\n(\"far\" pointer, segment + offset) and 16 bits, but...\n-- \nDr. Horst H. von Brand                   User #22616 counter.li.org\nDepartamento de Informatica                     Fono: +56 32 654431\nUniversidad Tecnica Federico Santa Maria              +56 32 654239\nCasilla 110-V, Valparaiso, Chile                Fax:  +56 32 797513\n"},{"id":"17520","messageId":"200603130414.k2D4EXcX011651@laptop11.inf.utfsm.cl","threadId":"3641","inReplyTo":"peff@peff.net","subject":"Re: [PATCH] Trivial warning fix for imap-send.c","fromName":"Horst von Brand","fromEmail":"vonbrand@inf.utfsm.cl","sentAt":"2006-03-13T04:14:33Z","receivedAt":"2006-03-13T04:14:33Z","isPatch":true,"sender":{"key":"vonbrand@inf.utfsm.cl","avatar":"https://avatars.githubusercontent.com/u/211384?v=4"},"body":"Jeff King <peff@peff.net> wrote:\n\n[...]\n\n> A void pointer is guaranteed to be able to hold any type of pointer\n> (either char * or struct foo * or whatever). The declaration of malloc\n> indicates a return of void *. On a platform where it matters, the\n> compiler generates code so that \n>   struct foo *bar = malloc(100);\n> converts the void * pointer into the correct size (in the same way that\n> assigning between differently sized integers works).\n\nRight.\n\n> This breaks down with variadic functions, which have no typing\n> information. So doing this:\n>   execl(\"foo\", \"bar\", my_struct_foo);\n> doesn't give the compiler a chance to do the implicit cast and you get\n> subtle breakage (in the same way that you would if you passed a long to\n> a variadic function expecting a short).\n\nIt just passes 3 \"void *\"'s, and casts back. What is so strange?\n-- \nDr. Horst H. von Brand                   User #22616 counter.li.org\nDepartamento de Informatica                     Fono: +56 32 654431\nUniversidad Tecnica Federico Santa Maria              +56 32 654239\nCasilla 110-V, Valparaiso, Chile                Fax:  +56 32 797513\n"},{"id":"17525","messageId":"Pine.LNX.4.64.0603130759320.3618@g5.osdl.org","threadId":"3641","inReplyTo":"200603130414.k2D4EXcX011651@laptop11.inf.utfsm.cl","subject":"Re: [PATCH] Trivial warning fix for imap-send.c","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-03-13T16:26:56Z","receivedAt":"2006-03-13T16:26:56Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 13 Mar 2006, Horst von Brand wrote:\n>> \n> > This breaks down with variadic functions, which have no typing\n> > information. So doing this:\n> >   execl(\"foo\", \"bar\", my_struct_foo);\n> > doesn't give the compiler a chance to do the implicit cast and you get\n> > subtle breakage (in the same way that you would if you passed a long to\n> > a variadic function expecting a short).\n> \n> It just passes 3 \"void *\"'s, and casts back. What is so strange?\n\nIt doesn't actually pass 3 \"void *\".\n\nVariadic functions pass their arguments as-is (apart from the normal \ninteger promotion for small integer types: chars are passed as integers if \n\"char\" is smaller than \"int\").\n\nSo no actual casting takes place for the arguments, and\n\n\texecl(\"foo\", \"bar\", my_struct_foo, NULL);\n\npasses in four pointers: two of type \"char *\", one of whatever \nmy_struct_foo is (\"struct foo *\") and finally hopefully one of \"void *\" \n(modulo broken compilers). They might - in theory - have different sizes \nand representations.\n\nNow, the interesting effect of this is that simple things like\n\n\tprintf(\"Pointer value %p\\n\", myfunction);\n\nis actually NOT STRICTLY PORTABLE CODE! Why? Because \"%p\" wants a void \npointer, but \"myfunction\" is of a different pointer type, which may \nactually have a different size and a different representation entirely, so \nyou can get total garbage printed out.\n\nSo you have two choices:\n\n - be sane, and ignore insane architectures. In this case, the above is \n   perfectly fine C code.\n\n - be insane, and care about it. In this case, you really do have to add \n   the casts to be safe in theory.\n\nThe \"%p\" for printf() is actually a wonderful example of why you really \nreally really should ignore language lawyers. According to language \nlawyers, you should add that \"(void *)\" cast. But look around for how many \nsuch casts you can find in real code, and realize that the language \nlawyers just don't matter. A C compiler environment that requires it is \nsimply broken, and sane people will refuse to use it for anything than \nsmall embedded work, because it's simply not usable.\n\nSo while it's not true in theory, in _practice_ you should expect all \npointers to be of the same size and use the same representation. Anything \nelse is just too painful to be ever worth bothering with.\n\n(Remember near and far pointers from 16-bit DOS/Windows? Those \nenvironments at least had _explicit_ pointer sizes, making the problem \nless horrible, but that was clearly a disaster nonetheless. Pointers that \nimplicitly have different sizes because they point to different types are \neven _worse_).\n\n\t\t\tLinus\n\nPS. Final words: while knowing that all pointer representations must be \nthe same, and that NULL actually must be the bitwise binary \"all zero\" \nvalue (otherwise \"memset(structptr, 0, structsize)\" would break), it's \nequally important to know that the standard doesn't _guarantee_ it. Why? \n\nBecause that way, when somebody tries to tell you that your code isn't \nstandards conformant and might be unportable, you can say \"yeah, I know, \nbut only a total loser would ever care\". Instead of incorrectly trying to \nargue that your code is \"correct\".\n"},{"id":"17535","messageId":"20060314004253.GA24668@coredump.intra.peff.net","threadId":"3641","inReplyTo":"200603130412.k2D4CW1b011631@laptop11.inf.utfsm.cl","subject":"[OT] Re: [PATCH] Use explicit pointers for execl...() sentinels.","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2006-03-14T00:42:53Z","receivedAt":"2006-03-14T00:42:53Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Mar 13, 2006 at 12:12:31AM -0400, Horst von Brand wrote:\n\n> Very improbable, they'll be the same normally (\"void *\" is a way of getting\n> rid of the overloading of the meaning of \"char *\" for this before ANSI C).\n> Sure, sizeof(int *) might be 4, but I think that is pretty far off.\n\nLet me clarify my position. The STANDARD doesn't guarantee such things.\nIn PRACTICE, for modern machines you can assume that all pointers are\nthe same size (and things like all-bits-zero is a null pointer) if it\nmakes your code cleaner. In other words, I agree with Linus: git should\nfollow what works in practice, but you should at least recognize that\nyou're violating the standard.\n\nThat being said, you appear to be making the argument that passing a\n'foo *' to a variadic function expecting a 'bar *' doesn't violate the\nstandard. I believe it invokes undefined behavior.\n\n> There are special rules for variadic functions, probably pointers would be\n> cast to/from void * in such a case by the compiler.\n\nThe rules indicate that arguments matching the '...' follow \"default\nargument promotion\".  See section 6.5.2.2, paragraph 7.  This default\npromotion is the same as what would happen if there were no prototype\nfor the function, and is defined in paragraph 6:\n  ...the integer promotions are performed on each argument, and arguments\n  that have type float are promoted to double.\nI don't see anything about promoting pointers to void.\n\nFurthermore, when accessing the arguments using va_arg, the types must\nmatch or the behavior is undefined, UNLESS (7.5.1.1, para 2):\n  - one type is signed and the other is the matching unsigned type\n  - one type is a pointer to void and the other is a pointer of\n    character type\nIOW, the standard does promise that void* and char* pointers are\nrepresented the same, but nothing else.\n\n> > If you remain unconvinced, I can try to find chapter and verse of the\n> > standard.\n> Please do.\n\nSee above.\n\n-Peff\n"},{"id":"297930","messageId":"200612051734.kB5HYBUs016133@laptop13.inf.utfsm.cl","threadId":"3641","inReplyTo":"peff@peff.net","subject":"Re: [PATCH] git-explain","fromName":"Horst H. von Brand","fromEmail":"vonbrand@inf.utfsm.cl","sentAt":"2006-12-05T17:34:11Z","receivedAt":"2006-12-05T17:34:11Z","isPatch":true,"sender":{"key":"vonbrand@inf.utfsm.cl","avatar":"https://avatars.githubusercontent.com/u/211384?v=4"},"body":"Jeff King <peff@peff.net> wrote:\n\n[...]\n\n> As long as the safety valves don't come up _routinely_ in certain\n> workflows, it seems OK to bypass them with a '-f' force switch. I\n> suspect the best way to figure out if such workflows are in use is to\n> put in the safety valves and see who complains; otherwise we're stuck\n> with brainstorming workflows and deciding whether they make sense.\n\nProblem is that nobody reads the manuals, next to nobody complains, and\nwhen it doesn't work out via road A you try plan B. A might have been\nexactly right, but it is blocked, and you'll never know if it is because of\nfundamental reasons or by decree.\n-- \nDr. Horst H. von Brand                   User #22616 counter.li.org\nDepartamento de Informatica                    Fono: +56 32 2654431\nUniversidad Tecnica Federico Santa Maria             +56 32 2654239\n"}]}