From ibob17 at yahoo.gr Sat Oct 10 05:21:35 2009 From: ibob17 at yahoo.gr (Vangelis Katsikaros) Date: Sat, 10 Oct 2009 15:21:35 +0300 Subject: [splint-discuss] nullwhentrue explained Message-ID: <4AD07C4F.1050009@yahoo.gr> Hello I am new to splint and I would like to ask a question about nullwhentrue. In "2.1.1 Predicate Functions" it says "If a function annotated with nullwhentrue returns true it means its first passed parameter is NULL. [1] If it returns false, the parameter is not NULL. [2] Note that it may return true for a parameter that is not NULL. [3] ..." Then in "Appendix C Annotations" it says: "nullwhentrue If result is true, first parameter is NULL." [4] So I am confused since I read that i) result true => first parameter is NULL [1], [4] ii) result false => first parameter is not NULL [2] iii) result true => (first?) parameter could be not NULL [3] I see a contradiction between i and iii, unless I haven't understood correctly or I miss something obvious. Is it result true => first parameter is whatever result false => first parameter is not NULL ? I haven't seen something in the FAQ or the archives of the list about this. Regards Vangelis Katsikaros PS. I don't have a specific case where I need this. I just started to use splint, and as I tried to read the first manual chapters, I stumbled on this. So, I am asking in case I am missing something basic here. From splint at sympatico.ca Sun Oct 11 12:29:14 2009 From: splint at sympatico.ca (Bill Pringlemeir) Date: Sun, 11 Oct 2009 14:29:14 -0500 Subject: [splint-discuss] nullwhentrue explained In-Reply-To: <4AD07C4F.1050009@yahoo.gr> (Vangelis Katsikaros's message of "Sat, 10 Oct 2009 15:21:35 +0300") References: <4AD07C4F.1050009@yahoo.gr> Message-ID: <87ws31afw5.fsf@sympatico.ca> On 10 Oct 2009, ibob17 at yahoo.gr wrote: > I am new to splint and I would like to ask a question about nullwhentrue. > > In "2.1.1 Predicate Functions" it says > > "If a function annotated with nullwhentrue returns true it means its > first passed parameter is NULL. [1] If it returns false, the parameter > is not NULL. [2] Note that it may return true for a parameter that is > not NULL. [3] ..." > > Then in "Appendix C Annotations" it says: > > "nullwhentrue > If result is true, first parameter is NULL." [4] > > So I am confused since I read that > > i) result true => first parameter is NULL [1], [4] > ii) result false => first parameter is not NULL [2] > iii) result true => (first?) parameter could be not NULL [3] > > I see a contradiction between i and iii, unless I haven't understood > correctly or I miss something obvious. > > Is it > result true => first parameter is whatever > result false => first parameter is not NULL > ? The intent is that the function annotated with this returns a 'go/no-go' status. Ie, there is some error or something wrong. Some code used a magic cookie to denote a type. struct foo { int magic; /* always 0x12348765 for foo struct */ ... } static /*@nullwhentrue@*/ bool checkFoo (/*@temp@*/ foo * _foo); The part [3] means that true may be returned if the 'magic' value is not as denoted. Some psuedo-code might be like this, bar * foo_to_bar(/*@null@*/ foo *_foo) { if(checkFoo(_foo)) return barRoot; return newBar(_foo); } Ie, some default value is returned on either NULL or if the foo does not seem to be valid. /* Please don't comment on where this is a correct thing to do in your nuclear reactor control system. */ static bool checkFoo (foo * _foo) { if(foo && foo->magic == 0x12348765) return TRUE; return FALSE; } So there is no 'assertion' about 'i)'. If the result is true, it doesn't *ensure* that arguement one was NULL. However, if argument one was NULL, then the return value is true. So, code that initially has a potential NULL value will be not NULL for the false case (ie case ii is correct). If a function annotated with this returns true, then the first parameter should not be used in that code path afterwards. For the false case, a possibly 'null' value is not longer possibly 'null' but is known to be good (non-null). fwiw, Bill Pringlemeir. -- ``C Code. C code run. Run, code, run... PLEASE!!!'' - Barbara Tongue From splint at sympatico.ca Sun Oct 11 12:29:14 2009 From: splint at sympatico.ca (Bill Pringlemeir) Date: Sun, 11 Oct 2009 14:29:14 -0500 Subject: [splint-discuss] nullwhentrue explained In-Reply-To: <4AD07C4F.1050009@yahoo.gr> (Vangelis Katsikaros's message of "Sat, 10 Oct 2009 15:21:35 +0300") References: <4AD07C4F.1050009@yahoo.gr> Message-ID: <87ws31afw5.fsf@sympatico.ca> On 10 Oct 2009, ibob17 at yahoo.gr wrote: > I am new to splint and I would like to ask a question about nullwhentrue. > > In "2.1.1 Predicate Functions" it says > > "If a function annotated with nullwhentrue returns true it means its > first passed parameter is NULL. [1] If it returns false, the parameter > is not NULL. [2] Note that it may return true for a parameter that is > not NULL. [3] ..." > > Then in "Appendix C Annotations" it says: > > "nullwhentrue > If result is true, first parameter is NULL." [4] > > So I am confused since I read that > > i) result true => first parameter is NULL [1], [4] > ii) result false => first parameter is not NULL [2] > iii) result true => (first?) parameter could be not NULL [3] > > I see a contradiction between i and iii, unless I haven't understood > correctly or I miss something obvious. > > Is it > result true => first parameter is whatever > result false => first parameter is not NULL > ? The intent is that the function annotated with this returns a 'go/no-go' status. Ie, there is some error or something wrong. Some code used a magic cookie to denote a type. struct foo { int magic; /* always 0x12348765 for foo struct */ ... } static /*@nullwhentrue@*/ bool checkFoo (/*@temp@*/ foo * _foo); The part [3] means that true may be returned if the 'magic' value is not as denoted. Some psuedo-code might be like this, bar * foo_to_bar(/*@null@*/ foo *_foo) { if(checkFoo(_foo)) return barRoot; return newBar(_foo); } Ie, some default value is returned on either NULL or if the foo does not seem to be valid. /* Please don't comment on where this is a correct thing to do in your nuclear reactor control system. */ static bool checkFoo (foo * _foo) { if(foo && foo->magic == 0x12348765) return TRUE; return FALSE; } So there is no 'assertion' about 'i)'. If the result is true, it doesn't *ensure* that arguement one was NULL. However, if argument one was NULL, then the return value is true. So, code that initially has a potential NULL value will be not NULL for the false case (ie case ii is correct). If a function annotated with this returns true, then the first parameter should not be used in that code path afterwards. For the false case, a possibly 'null' value is not longer possibly 'null' but is known to be good (non-null). fwiw, Bill Pringlemeir. -- ``C Code. C code run. Run, code, run... PLEASE!!!'' - Barbara Tongue From Michael.Wojcik at microfocus.com Mon Oct 12 01:00:14 2009 From: Michael.Wojcik at microfocus.com (Michael Wojcik) Date: Mon, 12 Oct 2009 01:00:14 -0700 Subject: [splint-discuss] nullwhentrue explained In-Reply-To: <87ws31afw5.fsf@sympatico.ca> References: <4AD07C4F.1050009@yahoo.gr> <87ws31afw5.fsf@sympatico.ca> Message-ID: <81F42F63D5BB344ABF294F8E80990C79CD5207@MTV-EXCHANGE.microfocus.com> > From: splint-discuss-bounces at cs.virginia.edu [mailto:splint-discuss- > bounces at cs.virginia.edu] On Behalf Of Bill Pringlemeir > Sent: Sunday, 11 October, 2009 20:29 > To: Discussions about the Splint annotation-assisted static analysis > project > > On 10 Oct 2009, ibob17 at yahoo.gr wrote: > > > I am new to splint and I would like to ask a question about > > nullwhentrue. > > So there is no 'assertion' about 'i)'. If the result is true, it > doesn't *ensure* that arguement one was NULL. However, if argument one > was NULL, then the return value is true. In short, the annotation is misnamed. It indicates the function returns true if the first argument is null [1]. The function may return true under other circumstances as well. Thus the annotation should be called "truewhennull", since that's the claim it makes. "nullwhentrue" is an incorrect description. Unfortunately, it's too late to fix it now. [1] If we want to be completely pedantic: A function in C can test whether a parameter is null; it can't test whether it's NULL. NULL is an object-like macro that evaluates to a null pointer constant, optionally cast to void *. Since macros are evaluated in translation, a function can't distinguish between a null pointer constant represented in the source by NULL and any other sort of null pointer. -- Michael Wojcik Principal Software Systems Developer, Micro Focus From splint at sympatico.ca Mon Oct 12 13:52:34 2009 From: splint at sympatico.ca (Bill Pringlemeir) Date: Mon, 12 Oct 2009 15:52:34 -0500 Subject: [splint-discuss] nullwhentrue explained References: <4AD07C4F.1050009@yahoo.gr> <87ws31afw5.fsf@sympatico.ca> <81F42F63D5BB344ABF294F8E80990C79CD5207@MTV-EXCHANGE.microfocus.com> Message-ID: <87y6ngcp2l.fsf@sympatico.ca> On 12 Oct 2009, Michael.Wojcik at microfocus.com wrote: >> On 10 Oct 2009, ibob17 at yahoo.gr wrote: >>> I am new to splint and I would like to ask a question about >>> nullwhentrue. >> So there is no 'assertion' about 'i)'. If the result is true, it >> doesn't *ensure* that arguement one was NULL. However, if argument >> one was NULL, then the return value is true. > In short, the annotation is misnamed. It indicates the function returns > true if the first argument is null [1]. The function may return true > under other circumstances as well. Thus the annotation should be called > "truewhennull", since that's the claim it makes. "nullwhentrue" is an > incorrect description. > Unfortunately, it's too late to fix it now. If that is really the problem ("truewhennull" versus "nullwhentrue") it is very easy to add a new annotation. "nullwhentrue" was originally named "truenull". They all map to the same thing underneath, this is just an extra key to add to the parsing level. It sets the 'QU_TRUENULL' qualifier to set the semantic machinery in either case. I was intending to add another parser that would understand gcc attribute() statements (which can also be useful for code generation). For the most part this is just a parsing level problem and the analysis algorithms are unchanged. I don't think that is the whole problem though. I think that "Predicate Functions" might better be titled "argument checkers" or something like that. People versed in Lisp, Lambda calculus, etc will easily grok "predicate functions". However, not everyone who uses 'C' would understand that nomenclature. Probably both would be helpful, but the OP has the benefit of experience, so if Vangelis could tell us if he understands now and what the confusion was that might be helpful. -- I never did give anybody hell. I just told the truth and they thought it was hell. - Harry S. Truman From ibob17 at yahoo.gr Tue Oct 13 07:36:34 2009 From: ibob17 at yahoo.gr (Vangelis Katsikaros) Date: Tue, 13 Oct 2009 17:36:34 +0300 Subject: [splint-discuss] nullwhentrue explained In-Reply-To: <87y6ngcp2l.fsf@sympatico.ca> References: <4AD07C4F.1050009@yahoo.gr> <87ws31afw5.fsf@sympatico.ca> <81F42F63D5BB344ABF294F8E80990C79CD5207@MTV-EXCHANGE.microfocus.com> <87y6ngcp2l.fsf@sympatico.ca> Message-ID: <4AD49072.8000805@yahoo.gr> Bill Pringlemeir wrote: > On 12 Oct 2009, Michael.Wojcik at microfocus.com wrote: > >>> On 10 Oct 2009, ibob17 at yahoo.gr wrote: > >>>> I am new to splint and I would like to ask a question about >>>> nullwhentrue. > >>> So there is no 'assertion' about 'i)'. If the result is true, it >>> doesn't *ensure* that arguement one was NULL. However, if argument >>> one was NULL, then the return value is true. > >> In short, the annotation is misnamed. It indicates the function returns >> true if the first argument is null [1]. The function may return true >> under other circumstances as well. Thus the annotation should be called >> "truewhennull", since that's the claim it makes. "nullwhentrue" is an >> incorrect description. > >> Unfortunately, it's too late to fix it now. > > If that is really the problem ("truewhennull" versus "nullwhentrue") > it is very easy to add a new annotation. "nullwhentrue" was > originally named "truenull". They all map to the same thing > underneath, this is just an extra key to add to the parsing level. It > sets the 'QU_TRUENULL' qualifier to set the semantic machinery in > either case. I was intending to add another parser that would > understand gcc attribute() statements (which can also be useful for > code generation). For the most part this is just a parsing level > problem and the analysis algorithms are unchanged. > > I don't think that is the whole problem though. I think that > "Predicate Functions" might better be titled "argument checkers" or > something like that. People versed in Lisp, Lambda calculus, etc will > easily grok "predicate functions". However, not everyone who uses 'C' > would understand that nomenclature. > > Probably both would be helpful, but the OP has the benefit of > experience, so if Vangelis could tell us if he understands now and > what the confusion was that might be helpful. > Hello Bill and Michael I think that the confusion started from the manual 2.1.1 where it says: "If a function annotated with nullwhentrue returns true it means its first passed parameter is NULL" and in Appendix C: "nullwhentrue If result is true, first parameter is NULL." from which I derived if returns true => arg 1 is NULL (a) whereas the correct one should be if arg 1 is NULL => returns true (b) So, is (b) the correct one, or have I made a complete mess? and also from what Bill said: >>> So, code that initially >>> has a potential NULL value will be not NULL for the false case (ie >>> case ii is correct) From this one I understand that (c) also stands correct for nullwhentrue. if returns false => arg 1 is NOT NULL (c) So there is one implication (=>) for the nature of the argument and one implication for the nature of the return result. If this is the case, then I think that the text in the manual is confusing and not the name of the annotation, or my lack of of Lambda calculus knowledge (for which BTW I have no clue, except some mentioning in a program analysis course). BTW, the way I try to understand how these things work (ie by converting them to a => "implication") is the proper way to understand them, or does this l-calulus/predicates changes things somehow? Don't shoot me if this question sounds totally stupid :P Thanks for your responses. Vangelis From Michael.Wojcik at microfocus.com Tue Oct 13 10:12:30 2009 From: Michael.Wojcik at microfocus.com (Michael Wojcik) Date: Tue, 13 Oct 2009 10:12:30 -0700 Subject: [splint-discuss] nullwhentrue explained In-Reply-To: <4AD49072.8000805@yahoo.gr> References: <4AD07C4F.1050009@yahoo.gr><87ws31afw5.fsf@sympatico.ca> <81F42F63D5BB344ABF294F8E80990C79CD5207@MTV-EXCHANGE.microfocus.com><87y6ngcp2l.fsf@sympatico.ca> <4AD49072.8000805@yahoo.gr> Message-ID: <81F42F63D5BB344ABF294F8E80990C79CD5214@MTV-EXCHANGE.microfocus.com> > From: splint-discuss-bounces at cs.virginia.edu [mailto:splint-discuss- > bounces at cs.virginia.edu] On Behalf Of Vangelis Katsikaros > Sent: Tuesday, 13 October, 2009 15:37 > > > I think that the confusion started from the manual 2.1.1 where it says: > "If a function annotated with nullwhentrue returns true it means its > first passed parameter is NULL" > and in Appendix C: > "nullwhentrue > If result is true, first parameter is NULL." > > from which I derived > if returns true => arg 1 is NULL (a) > > whereas the correct one should be > if arg 1 is NULL => returns true (b) > > So, is (b) the correct one, or have I made a complete mess? Correct (assuming *I* have understood this discussion correctly!). The documentation appears to have it backward: a function annotated with nullwhentrue will return true if the first parameter is null - your (b) - but the reverse implication is not true. That is, int foo(void *bar) { return 1; } could be annotated with nullwhentrue, since it returns true if the first argument is null. But clearly it also returns true when the first argument is not null. > and also from what Bill said: > >>> So, code that initially > >>> has a potential NULL value will be not NULL for the false case (ie > >>> case ii is correct) > From this one I understand that (c) also > stands correct for nullwhentrue. > if returns false => arg 1 is NOT NULL (c) That's my understanding. > So there is one implication (=>) for the nature of the argument and one > implication for the nature of the return result. (c) follows from (b). [It's a basic theorem of propositional calculus, known as modus tollens: p => q, !q | !p. You can also write this in basic logic as (p => q) => (q' => p'), or "if p implies q, but q is false, then p must be false".] > If this is the case, then I think that the text in the manual is > confusing and not the name of the annotation, Those aren't exclusive. Both the text in the manual and the name of the annotation are wrong. > BTW, the way I try to understand how these things work (ie by converting > them to a => "implication") is the proper way to understand them, It's a perfectly good way. Some people are comfortable with logic notation; some people like to work other ways. Lambda calculus is more expressive than basic propositional logic, but either does fine for a relatively simple question like this one. > does this l-calulus/predicates changes things somehow? No. Bill just mentioned lambda calculus because the word "predicate" is used in that context, so he thought it might be more familiar to people who had that experience. -- Michael Wojcik Principal Software Systems Developer, Micro Focus From Michael.Wojcik at microfocus.com Tue Oct 13 10:13:04 2009 From: Michael.Wojcik at microfocus.com (Michael Wojcik) Date: Tue, 13 Oct 2009 10:13:04 -0700 Subject: [splint-discuss] nullwhentrue explained In-Reply-To: <87y6ngcp2l.fsf@sympatico.ca> References: <4AD07C4F.1050009@yahoo.gr> <87ws31afw5.fsf@sympatico.ca><81F42F63D5BB344ABF294F8E80990C79CD5207@MTV-EXCHANGE.microfocus.com> <87y6ngcp2l.fsf@sympatico.ca> Message-ID: <81F42F63D5BB344ABF294F8E80990C79CD5215@MTV-EXCHANGE.microfocus.com> > From: splint-discuss-bounces at cs.virginia.edu [mailto:splint-discuss- > bounces at cs.virginia.edu] On Behalf Of Bill Pringlemeir > Sent: Monday, 12 October, 2009 21:53 > > On 12 Oct 2009, Michael.Wojcik at microfocus.com wrote: > >> On 10 Oct 2009, ibob17 at yahoo.gr wrote: > > >>> I am new to splint and I would like to ask a question about > >>> nullwhentrue. > > > In short, the annotation is misnamed.... > > > Unfortunately, it's too late to fix it now. > > If that is really the problem ("truewhennull" versus "nullwhentrue") it > is very easy to add a new annotation. "nullwhentrue" was originally > named "truenull". They all map to the same thing underneath, this is > just an extra key to add to the parsing level. Ah. That's good. For some reason, I was thinking that we'd have to change the name, not just add another name for the same qualifier. That sounds good to me. By the way, Bill, it's great to see you doing all this work on Splint. I remember there were several years when it didn't seem there was much (if any) maintenance being done on it. -- Michael Wojcik Principal Software Systems Developer, Micro Focus From splint at sympatico.ca Tue Oct 13 14:26:14 2009 From: splint at sympatico.ca (Bill Pringlemeir) Date: Tue, 13 Oct 2009 16:26:14 -0500 Subject: [splint-discuss] nullwhentrue explained In-Reply-To: <81F42F63D5BB344ABF294F8E80990C79CD5214@MTV-EXCHANGE.microfocus.com> (Michael Wojcik's message of "Tue, 13 Oct 2009 10:12:30 -0700") References: <4AD07C4F.1050009@yahoo.gr> <87ws31afw5.fsf@sympatico.ca> <81F42F63D5BB344ABF294F8E80990C79CD5207@MTV-EXCHANGE.microfocus.com> <87y6ngcp2l.fsf@sympatico.ca> <4AD49072.8000805@yahoo.gr> <81F42F63D5BB344ABF294F8E80990C79CD5214@MTV-EXCHANGE.microfocus.com> Message-ID: <87k4yzx9xl.fsf@sympatico.ca> On 13 Oct 2009, Michael.Wojcik at microfocus.com wrote: >> Vangelis Katsikaros Wrote: >> Sent: Tuesday, 13 October, 2009 15:37 >> I think that the confusion started from the manual 2.1.1 where it says: >> "If a function annotated with nullwhentrue returns true it means >> its first passed parameter is NULL" Ah, but I think you should always read a whole paragraph. If a function annotated with nullwhentrue returns true it means its first passed parameter is NULL. If it returns false, the parameter is not NULL. Note that it may return true for a parameter that is not NULL. A more descriptive name for nullwhentrue would be "if the result is false, the parameter was not null". The "more descriptive name" is the correct description. The use of 'NULL' is also confusing. Really 'NULL' denotes that splint will emit an error if this value is used. >> and in Appendix C: >> "nullwhentrue >> If result is true, first parameter is NULL." It should be as the "falsewhennull" description, If result is FALSE, first parameter is not NULL. *OR* If result is TRUE, first parameter is not accessible. >> If this is the case, then I think that the text in the manual is >> confusing and not the name of the annotation, > Those aren't exclusive. Both the text in the manual and the name of the > annotation are wrong. The annotation name is wrong/confusing from a logic/English perspective. The statement "returns true when null" is correct. The statement "null when returning true" is not. The statement "un-useable/not accessible when true" is the intent. So "truewhennull" might seem better, but "unusablewhentrue" is probably a better annotation. This annotation is for use of the function, versus the implementation of the function. The function, int foo(char *bar) { return 1; } says that bar is always un-usable. However, the user of 'foo()' in another module, void bazzle(char *bar) { if(foo(bar)) /* with "truewhennull" splint knows bar illegal here.*/; else { /* fine to use bar here.*/ printf("The bar is set to %c.\n", *bar); } } is possibly also important. Especially as at some point you might decide that some type of 'bar' is worthwhile. The whole intent of the predicate functions is that you may wish to 'refactor' error checking logic into a 'go/no-go' function. The predicate annotation allows splint to understand which branch of an if/else has a valid 'bar'. Splint does not validate the predicate function, just the flow control of the users of 'foo()'; bazzle() in the snippet above. This does seem clear to me if I read the whole section 2.1.1. The appendix does not stand well by itself; if you start in the appendix you can easily get confused. I have no access to the FAQ or the manual. However, the mailing list is publicly accessible. I am inclined to leave the annotation as it is for now (and not add another variant). Fwiw, Bill Pringlemeir. -- Washing one's hands of the conflict between the powerful and the powerless means to side with the powerful, not to be neutral. - Freire From ibob17 at yahoo.gr Wed Oct 14 02:46:13 2009 From: ibob17 at yahoo.gr (Vangelis Katsikaros) Date: Wed, 14 Oct 2009 12:46:13 +0300 Subject: [splint-discuss] nullwhentrue explained In-Reply-To: <87k4yzx9xl.fsf@sympatico.ca> References: <4AD07C4F.1050009@yahoo.gr> <87ws31afw5.fsf@sympatico.ca> <81F42F63D5BB344ABF294F8E80990C79CD5207@MTV-EXCHANGE.microfocus.com> <87y6ngcp2l.fsf@sympatico.ca> <4AD49072.8000805@yahoo.gr> <81F42F63D5BB344ABF294F8E80990C79CD5214@MTV-EXCHANGE.microfocus.com> <87k4yzx9xl.fsf@sympatico.ca> Message-ID: <4AD59DE5.4070304@yahoo.gr> Bill Pringlemeir wrote: > On 13 Oct 2009, Michael.Wojcik at microfocus.com wrote: > >>> Vangelis Katsikaros Wrote: >>> Sent: Tuesday, 13 October, 2009 15:37 > >>> I think that the confusion started from the manual 2.1.1 where it says: >>> "If a function annotated with nullwhentrue returns true it means >>> its first passed parameter is NULL" > > Ah, but I think you should always read a whole paragraph. > > If a function annotated with nullwhentrue returns true it means its > first passed parameter is NULL. If it returns false, the parameter > is not NULL. Note that it may return true for a parameter that is > not NULL. A more descriptive name for nullwhentrue would be "if the > result is false, the parameter was not null". > > The "more descriptive name" is the correct description. The use of > 'NULL' is also confusing. Really 'NULL' denotes that splint will emit > an error if this value is used. Hi Yes, ?'ve seen that. The problem, from my point of view, is that there is no clear separation of the definition itself and an further explanation/discussion of the definition. This is what complicates things. Then, the Appendix text simply broadens the confusion. Also, I think that, in the text, the usage of "usable/accessible" might be more appropriate than null, since null is one case of not usable. And also an explanation of "usable", similar to the one you provided. >>> and in Appendix C: >>> "nullwhentrue >>> If result is true, first parameter is NULL." > > It should be as the "falsewhennull" description, > > If result is FALSE, first parameter is not NULL. Ok this is clear things now. > *OR* > > If result is TRUE, first parameter is not accessible. With your explanation of the go/no-go functions, this it totally clear too. True indicates that the first parameter is not-accessible for implementation specific reasons (not the correct type or whatever). Thank you both for both your time and your detailed explanations, Vangelis Katsikaros >>> If this is the case, then I think that the text in the manual is >>> confusing and not the name of the annotation, > >> Those aren't exclusive. Both the text in the manual and the name of the >> annotation are wrong. > > The annotation name is wrong/confusing from a logic/English > perspective. The statement "returns true when null" is correct. The > statement "null when returning true" is not. The statement > "un-useable/not accessible when true" is the intent. So > "truewhennull" might seem better, but "unusablewhentrue" is probably a > better annotation. This annotation is for use of the function, versus > the implementation of the function. The function, > > int foo(char *bar) { > return 1; > } > > says that bar is always un-usable. However, the user of 'foo()' in > another module, > > void bazzle(char *bar) { > if(foo(bar)) > /* with "truewhennull" splint knows bar illegal here.*/; > else { > /* fine to use bar here.*/ > printf("The bar is set to %c.\n", *bar); > } > } > > is possibly also important. Especially as at some point you might > decide that some type of 'bar' is worthwhile. > > The whole intent of the predicate functions is that you may wish to > 'refactor' error checking logic into a 'go/no-go' function. The > predicate annotation allows splint to understand which branch of an > if/else has a valid 'bar'. Splint does not validate the predicate > function, just the flow control of the users of 'foo()'; bazzle() in > the snippet above. This does seem clear to me if I read the whole > section 2.1.1. The appendix does not stand well by itself; if you > start in the appendix you can easily get confused. > > I have no access to the FAQ or the manual. However, the mailing list > is publicly accessible. I am inclined to leave the annotation as it > is for now (and not add another variant). From Michael.Wojcik at microfocus.com Fri Oct 16 02:53:58 2009 From: Michael.Wojcik at microfocus.com (Michael Wojcik) Date: Fri, 16 Oct 2009 02:53:58 -0700 Subject: [splint-discuss] nullwhentrue explained In-Reply-To: <87k4yzx9xl.fsf@sympatico.ca> References: <4AD07C4F.1050009@yahoo.gr> <87ws31afw5.fsf@sympatico.ca><81F42F63D5BB344ABF294F8E80990C79CD5207@MTV-EXCHANGE.microfocus.com><87y6ngcp2l.fsf@sympatico.ca> <4AD49072.8000805@yahoo.gr><81F42F63D5BB344ABF294F8E80990C79CD5214@MTV-EXCHANGE.microfocus.com> <87k4yzx9xl.fsf@sympatico.ca> Message-ID: <81F42F63D5BB344ABF294F8E80990C79CD522A@MTV-EXCHANGE.microfocus.com> > From: splint-discuss-bounces at cs.virginia.edu [mailto:splint-discuss- > bounces at cs.virginia.edu] On Behalf Of Bill Pringlemeir > Sent: Tuesday, 13 October, 2009 22:26 > To: Discussions about the Splint annotation-assisted static analysis > project > Subject: Re: [splint-discuss] nullwhentrue explained [snip explanation of nullwhentrue annotation] Thanks for that detailed and clear explanation, Bill. I need to look more closely at the annotation features when I have a free moment. -- Michael Wojcik Principal Software Systems Developer, Micro Focus From ibob17 at yahoo.gr Sat Oct 24 07:03:12 2009 From: ibob17 at yahoo.gr (Vangelis Katsikaros) Date: Sat, 24 Oct 2009 17:03:12 +0300 Subject: [splint-discuss] Dependent storage assigned to unqualified Message-ID: <4AE30920.8020402@yahoo.gr> Hello I have encountered a "Dependent storage assigned to unqualified" warning but I couldn't find sufficient information to understand what this is about. $ splint -exportlocal dep.c Splint 3.1.2 --- 11 May 2008 dep.c: (in function main) dep.c:41:5: Dependent storage assigned to unqualified: FARRAY[i] = fopen(cur_path, "r") Dependent storage is transferred to a non-dependent reference. (Use -dependenttrans to inhibit warning) Finished checking --- 1 code warning I understand that the warning has to do with "5 Memory Management" and more especially with "5.2.1 Unshared References", but I fail to see the connection. Any hints would be valuable :) Regards Vangelis Katsikaros PS. There is only one reference of dependent-trans on the manual which doesn't provide much information (it can only be found in page 83). //=========================================================== #include #include #define SIZE 4 /* we want to read several file (here SIZE) that have the same prefix. So we append an integer [0..9] to the basepath. Then we open the file of the appended path */ int main(){ int i = 0; int read_chars = 0; FILE* FARRAY[ SIZE ]; char basepath[] = "./directory/fileprefix_"; char* cur_path = NULL; for( i = 0; i < SIZE; i++ ){ // allocate cur_path = ( char* ) malloc( ( sizeof( basepath ) + 2 ) * sizeof( char ) ); if( cur_path == NULL ){ exit(0); } read_chars = snprintf( cur_path, ( sizeof( basepath ) + 1 ), "%s%d", basepath, i ); printf("%s\n", cur_path ); if( read_chars <= 0 ){ exit(0); } FARRAY[ i ] = fopen( cur_path, "r"); if( FARRAY[ i ] == NULL ){ exit(0); } free(cur_path); } // finish with reading the files for( i = 0; i < SIZE; i++ ){ (void)fclose( FARRAY[ i ] ); } return 0; } //=========================================================== From splint at sympatico.ca Sat Oct 24 12:19:53 2009 From: splint at sympatico.ca (Bill Pringlemeir) Date: Sat, 24 Oct 2009 14:19:53 -0500 Subject: [splint-discuss] Dependent storage assigned to unqualified In-Reply-To: <4AE30920.8020402@yahoo.gr> (Vangelis Katsikaros's message of "Sat, 24 Oct 2009 17:03:12 +0300") References: <4AE30920.8020402@yahoo.gr> Message-ID: <877huky4yu.fsf@sympatico.ca> On 24 Oct 2009, ibob17 at yahoo.gr wrote: > I have encountered a "Dependent storage assigned to unqualified" warning > but I couldn't find sufficient information to understand what this is about. > $ splint -exportlocal dep.c > Splint 3.1.2 --- 11 May 2008 > dep.c: (in function main) > dep.c:41:5: Dependent storage assigned to unqualified: > FARRAY[i] = fopen(cur_path, "r") > Dependent storage is transferred to a non-dependent reference. (Use > -dependenttrans to inhibit warning) You are using an 'annotated' version of fopen() and have enabled some of the annotation tracking. I think that you actually want to look at section '5.2.3' of the manual. I have the following annotation in splints 'lib/standard.h' file. /*@null@*/ /*@dependent@*/ FILE *fopen (char *filename, char *mode) This says that fopen() can return null and the returned value is a dependent. It needs to be 'owned' by something. However, the fclose() is not annotated to take this. The following produces no warning for me, + /*@dependent@*/ FILE* FARRAY[ SIZE ]; - FILE* FARRAY[ SIZE ]; $ splint +nof -exportlocal test.c Splint 3.1.2 --- 08 Sep 2009 Finished checking --- no warnings You might also wish to use the file.mts and filerw.mts files to track file usage. Splint will crash if you put this in the .splintrc. You can invoke it with, $ splint +nof -exportlocal -mts file -mts filerw test.c These are canned metastate files which take into account the additional states that files may have. Unfortunately, there are no annotated 'standard.h' that you can use to take these additional states into account. I am not also sure why fopen() isn't annotated with /*@owned@*/? Also, commenting out the 'fclose()' line doesn't seem to give me an error. This is the whole point of this tracking. The /*@owned@*/ annotation is the better choice as it indicated that the fopen() return value must be closed. Also, I don't know if you have anything in your '~/.splintrc'? The annotations actually make splint as powerful (in theory) as tools like PolySpace Verifier, Coverity Prevent and Klocwork K7. These tools perform global analysis and create there own 'annotations'. If splint (or a tool like splint) has correct annotation, then it should be able to do as much as these tools more efficiently. This can bring the 'design by contract' to languages that don't natively support it. http://en.wikipedia.org/wiki/Design_by_contract The following changed to standard.h seem to have file tracking working for me, cvs diff standard.h Index: standard.h =================================================================== RCS file: /cvsroot/splint/splint/lib/standard.h,v retrieving revision 1.13 diff -r1.13 standard.h 524c524 < int fclose (FILE *stream) --- > int fclose ( /*@owned@*/FILE *stream) 530c530 < /*@null@*/ /*@dependent@*/ FILE *fopen (char *filename, char *mode) --- > /*@null@*/ /*@owned@*/ FILE *fopen (char *filename, char *mode) 533c533 < /*@dependent@*/ /*@null@*/ FILE *freopen (char *filename, char *mode, FILE *stream) --- > /*@owned@*/ /*@null@*/ FILE *freopen (char *filename, char *mode, /*@owned@*/FILE *stream) Unfortunately this seems to break some of the test cases. Also, I am trying to fix something else, so I dont' feel confident checking in these changes until the test code is functioning as expected [and a code review here can't hurt]. I have to call 'fclose()' with a file returned from 'fopen()' with this change. There may also be something wrong or difficult with an array of files. You will need to use the /*@owned@*/ annotation as opposed to /*@dependent@*/ which is in the released version of splint... Actually, /*@only@*/ seems to make most sense to me for the 'FILE*'; I don't see why it is different than malloc()/free(). I seem to remember having trouble with files when I was using splint on other projects... fwiw, Bill Pringlemeir. -- It is reasoning and faith that bind truth . - Rod Ryker... From splint at sympatico.ca Sat Oct 24 12:19:53 2009 From: splint at sympatico.ca (Bill Pringlemeir) Date: Sat, 24 Oct 2009 14:19:53 -0500 Subject: [splint-discuss] Dependent storage assigned to unqualified In-Reply-To: <4AE30920.8020402@yahoo.gr> (Vangelis Katsikaros's message of "Sat, 24 Oct 2009 17:03:12 +0300") References: <4AE30920.8020402@yahoo.gr> Message-ID: <877huky4yu.fsf@sympatico.ca> On 24 Oct 2009, ibob17 at yahoo.gr wrote: > I have encountered a "Dependent storage assigned to unqualified" warning > but I couldn't find sufficient information to understand what this is about. > $ splint -exportlocal dep.c > Splint 3.1.2 --- 11 May 2008 > dep.c: (in function main) > dep.c:41:5: Dependent storage assigned to unqualified: > FARRAY[i] = fopen(cur_path, "r") > Dependent storage is transferred to a non-dependent reference. (Use > -dependenttrans to inhibit warning) You are using an 'annotated' version of fopen() and have enabled some of the annotation tracking. I think that you actually want to look at section '5.2.3' of the manual. I have the following annotation in splints 'lib/standard.h' file. /*@null@*/ /*@dependent@*/ FILE *fopen (char *filename, char *mode) This says that fopen() can return null and the returned value is a dependent. It needs to be 'owned' by something. However, the fclose() is not annotated to take this. The following produces no warning for me, + /*@dependent@*/ FILE* FARRAY[ SIZE ]; - FILE* FARRAY[ SIZE ]; $ splint +nof -exportlocal test.c Splint 3.1.2 --- 08 Sep 2009 Finished checking --- no warnings You might also wish to use the file.mts and filerw.mts files to track file usage. Splint will crash if you put this in the .splintrc. You can invoke it with, $ splint +nof -exportlocal -mts file -mts filerw test.c These are canned metastate files which take into account the additional states that files may have. Unfortunately, there are no annotated 'standard.h' that you can use to take these additional states into account. I am not also sure why fopen() isn't annotated with /*@owned@*/? Also, commenting out the 'fclose()' line doesn't seem to give me an error. This is the whole point of this tracking. The /*@owned@*/ annotation is the better choice as it indicated that the fopen() return value must be closed. Also, I don't know if you have anything in your '~/.splintrc'? The annotations actually make splint as powerful (in theory) as tools like PolySpace Verifier, Coverity Prevent and Klocwork K7. These tools perform global analysis and create there own 'annotations'. If splint (or a tool like splint) has correct annotation, then it should be able to do as much as these tools more efficiently. This can bring the 'design by contract' to languages that don't natively support it. http://en.wikipedia.org/wiki/Design_by_contract The following changed to standard.h seem to have file tracking working for me, cvs diff standard.h Index: standard.h =================================================================== RCS file: /cvsroot/splint/splint/lib/standard.h,v retrieving revision 1.13 diff -r1.13 standard.h 524c524 < int fclose (FILE *stream) --- > int fclose ( /*@owned@*/FILE *stream) 530c530 < /*@null@*/ /*@dependent@*/ FILE *fopen (char *filename, char *mode) --- > /*@null@*/ /*@owned@*/ FILE *fopen (char *filename, char *mode) 533c533 < /*@dependent@*/ /*@null@*/ FILE *freopen (char *filename, char *mode, FILE *stream) --- > /*@owned@*/ /*@null@*/ FILE *freopen (char *filename, char *mode, /*@owned@*/FILE *stream) Unfortunately this seems to break some of the test cases. Also, I am trying to fix something else, so I dont' feel confident checking in these changes until the test code is functioning as expected [and a code review here can't hurt]. I have to call 'fclose()' with a file returned from 'fopen()' with this change. There may also be something wrong or difficult with an array of files. You will need to use the /*@owned@*/ annotation as opposed to /*@dependent@*/ which is in the released version of splint... Actually, /*@only@*/ seems to make most sense to me for the 'FILE*'; I don't see why it is different than malloc()/free(). I seem to remember having trouble with files when I was using splint on other projects... fwiw, Bill Pringlemeir. -- It is reasoning and faith that bind truth . - Rod Ryker... From ibob17 at yahoo.gr Sat Oct 24 12:50:39 2009 From: ibob17 at yahoo.gr (Vangelis Katsikaros) Date: Sat, 24 Oct 2009 22:50:39 +0300 Subject: [splint-discuss] Dependent storage assigned to unqualified In-Reply-To: <877huky4yu.fsf@sympatico.ca> References: <4AE30920.8020402@yahoo.gr> <877huky4yu.fsf@sympatico.ca> Message-ID: <4AE35A8F.4080406@yahoo.gr> Bill Pringlemeir wrote: > > Also, I don't know if you have anything in your '~/.splintrc'? Hi Lots of information to accumulate! I need some time and reading before answering or asking more questions :) However, no I don't have created a .splintrc and there isn't any available, in case that helps. Regards Vangelis Katsikaros From D.Jansen at cs.ru.nl Sat Oct 24 14:33:31 2009 From: D.Jansen at cs.ru.nl (David N. Jansen) Date: Sat, 24 Oct 2009 23:33:31 +0200 Subject: [splint-discuss] /*@owned@*/ fopen()? In-Reply-To: <877huky4yu.fsf@sympatico.ca> References: <4AE30920.8020402@yahoo.gr> <877huky4yu.fsf@sympatico.ca> Message-ID: Op 24-okt-2009, om 21:19 heeft Bill Pringlemeir het volgende geschreven: > I am not also sure why fopen() isn't annotated with /*@owned@*/? > Also, commenting out the 'fclose()' line doesn't seem to give me an > error. This is the whole point of this tracking. The /*@owned@*/ > annotation is the better choice as it indicated that the fopen() > return value must be closed. A possible implementation of fopen() has statically allocated buffers, and fopen() would then return a pointer to one of them. In these implementations, fopen() cannot have type /*@owned@*/. Additionally, the C standard explicitly states that files are closed upon calling exit(), so the user is not required to close them himself. (Although splint will not complain if the files are closed by exit(), as this syntactically is just a function call.) Finally, I can find discussions on the web that suggest that fclose (stdout) is legal. David N. Jansen. From splint at sympatico.ca Sat Oct 24 16:08:33 2009 From: splint at sympatico.ca (Bill Pringlemeir) Date: Sat, 24 Oct 2009 18:08:33 -0500 Subject: [splint-discuss] splint bugs on sourceforge.net In-Reply-To: <20080414191451.GC3873@loktak.appaji.net> (Y. Giridhar Appaji Nag's message of "Tue, 15 Apr 2008 00:44:53 +0530") References: <20080414191451.GC3873@loktak.appaji.net> Message-ID: <87ocnwwfta.fsf@sympatico.ca> On 14 Apr 2008, giridhar at appaji.net wrote: > Does someone monitor the bugs reported on splint at the sourceforge.net > bugs / patches trackers? > I filed a few bugs and atleast one patch there that Debain splint users > have reported. Maybe some of them should make their way into the bugs > page at http://www.splint.org/bugs.html I am looking at them. I think that most of them have been fixed in CVS with the exception of the C99 ones. I would prefer to include a completely different grammar for processing C99 source to patching the existing file. For example, http://www.lysator.liu.se/c/ANSI-C-grammar-y.html etc. I am not really sure that the current grammar is the best to proceed with? Keeping the existing one for a C89 processing will maintain backwards compatibility. I would also like to update the gcc parsing abilities. Unfortunately, there are many data structure for maintaining symbols; ctype, ctbase, usymtab, uentry, ekind, usymId, etc. I am currently trying to ascertain what each of them do. I think that there is also some opportunity to refactor them to fewer types. Thanks, Bill Pringlemeir. -- The weakest among us, often show the most strength. From evans at cs.virginia.edu Sat Oct 24 16:13:32 2009 From: evans at cs.virginia.edu (David Evans) Date: Sat, 24 Oct 2009 19:13:32 -0400 Subject: [splint-discuss] splint bugs on sourceforge.net In-Reply-To: <87ocnwwfta.fsf@sympatico.ca> References: <20080414191451.GC3873@loktak.appaji.net> <87ocnwwfta.fsf@sympatico.ca> Message-ID: <4AE38A1C.7070907@cs.virginia.edu> Bill Pringlemeir wrote: > On 14 Apr 2008, giridhar at appaji.net wrote: > >> Does someone monitor the bugs reported on splint at the sourceforge.net >> bugs / patches trackers? > >> I filed a few bugs and atleast one patch there that Debain splint users >> have reported. Maybe some of them should make their way into the bugs >> page at http://www.splint.org/bugs.html > > I am looking at them. I think that most of them have been fixed in > CVS with the exception of the C99 ones. I would prefer to include a > completely different grammar for processing C99 source to patching the > existing file. For example, > > http://www.lysator.liu.se/c/ANSI-C-grammar-y.html > etc. > > I am not really sure that the current grammar is the best to proceed > with? Keeping the existing one for a C89 processing will maintain > backwards compatibility. I would also like to update the gcc parsing > abilities. > Yes, I agree that it would make a lot more sense to replace the grammar entirely than to try to make tweaks to it to support C99. Unfortunately, the splint design is rather awkward here, and was done by someone (that's me) who didn't have much clue about the right way to build a language analysis tool at the time. A better design would just use the parser as a front end to produce an intermediate representation which would be used for all the analysis, but the actually implementation intertwines the parsing and analysis much more than it should. If Bill and/or others have the energy to do it, the right approach would be to refactor splint to use a well-defined IR for the analysis, and support different front ends for parsing different languages. This would involve quite a bit of effort, but enable a much more maintainable and versatile tool, and in the long run be much better than adding special cases to the existing grammar to support C99. (One complexity in plugging in standard front ends is adding support for annotations in the grammar.) > Unfortunately, there are many data structure for maintaining symbols; > ctype, ctbase, usymtab, uentry, ekind, usymId, etc. I am currently > trying to ascertain what each of them do. I think that there is also > some opportunity to refactor them to fewer types. > The main thing that is awkward here is the way the static and path-sensitive information is combined in the usymtab. The usymtab is the symbol table, but it is actually a tree of symbol tables that keeps track of properties along different program paths (the comments at the beginning of usymtab.c give a rough idea what is done). A better design would separate the static symbol table (similar to what a normal compiler would have for each scope, with the information from annotations added) from the path-specific tables needed for the analysis. There are definitely opportunities to improve and simplify the design of the other parts, but I think cleaning up the way the symbol table/path-sensitive state is handled would be the most important improvement. Best, --- Dave From schonm at yahoo.com Sat Oct 24 21:15:30 2009 From: schonm at yahoo.com (J Schonberg) Date: Sat, 24 Oct 2009 21:15:30 -0700 (PDT) Subject: [splint-discuss] splint bugs on sourceforge.net In-Reply-To: <4AE38A1C.7070907@cs.virginia.edu> Message-ID: <826726.42318.qm@web58806.mail.re1.yahoo.com> --- On Sat, 10/24/09, David Evans wrote: > From: David Evans > Subject: Re: [splint-discuss] splint bugs on sourceforge.net > To: "Discussions about the Splint annotation-assisted static analysis project" > A better > design would just > use the parser as a front end to produce an intermediate > representation > which would be used for all the analysis, but the actually > implementation intertwines the parsing and analysis much > more than it should. Is this the approach being taken by ggcc? http://ggcc.info/ Perhaps an splint plugin to their frame work would be the way to go? Best wishes, Jason. From splint at sympatico.ca Sun Oct 25 14:25:35 2009 From: splint at sympatico.ca (Bill Pringlemeir) Date: Sun, 25 Oct 2009 17:25:35 -0500 Subject: [splint-discuss] /*@owned@*/ fopen()? References: <4AE30920.8020402@yahoo.gr> <877huky4yu.fsf@sympatico.ca> Message-ID: <87aazfw1pc.fsf@sympatico.ca> > Op 24-okt-2009, om 21:19 heeft Bill Pringlemeir het volgende geschreven: >> I am not also sure why fopen() isn't annotated with /*@owned@*/? >> Also, commenting out the 'fclose()' line doesn't seem to give me an >> error. This is the whole point of this tracking. The /*@owned@*/ >> annotation is the better choice as it indicated that the fopen() >> return value must be closed. On 24 Oct 2009, D.Jansen at cs.ru.nl wrote: > A possible implementation of fopen() has statically allocated > buffers, and fopen() would then return a pointer to one of them. In > these implementations, fopen() cannot have type /*@owned@*/. Hmm. You can implement malloc this way as well. The fact is that the memory region [or file] is owned by the caller of malloc() [or fopen()]. They return it to a pool by calling free() [or fclose()]. At the allocator level, everything is static; you only have as much memory as the system has. > Additionally, the C standard explicitly states that files are closed > upon calling exit(), so the user is not required to close them > himself. (Although splint will not complain if the files are closed > by exit(), as this syntactically is just a function call.) The same can be said for memory allocate with malloc(). sbrk() and friends will associate the memory for a process and the OS/kernel should reclaim any tables associated with them when the process exits. I think that most people would like unmatched fopen()/fclose() calls to be flagged. It is a design choice to depend on this. Some people believe that malloc() should be wrapped and call exit() if memory is exhausted. If someone did an analysis of the memory usage, this might be a valid strategy. However, for many designs code should free memory that is allocated. I think the same can be said for file, sockets, etc. I have debugged problems where the code had opened 1024+ files in a production environment. It went through several years of QA and no one detected this issue. Other people had implemented sanity checks in legacy code and if a condition didn't work the process would exit to be re-spawned by inittab/crontab. The code was turned into a SOA service and this behavior was no longer acceptable. I think it is useful to have a tools that would detect files opened, but not closed. I can see that some designs wouldn't care about this. I also think that it would be least surprising for splint to detect this and if a design relies on exit() to close files, an annotation would be good documentation of this fact. > Finally, I can find discussions on the web that suggest that fclose > (stdout) is legal. Yes, I think that stdin/stdout/stderr would have to be flagged as initialized somehow. However, that is a separate issue isn't it? Thanks, Bill Pringlemeir. -- Someday we'll look back on all this and plow into a parked car. From splint at sympatico.ca Sun Oct 25 18:40:42 2009 From: splint at sympatico.ca (Bill Pringlemeir) Date: Sun, 25 Oct 2009 21:40:42 -0500 Subject: [splint-discuss] splint bugs on sourceforge.net In-Reply-To: <826726.42318.qm@web58806.mail.re1.yahoo.com> (J. Schonberg's message of "Sat, 24 Oct 2009 21:15:30 -0700 (PDT)") References: <826726.42318.qm@web58806.mail.re1.yahoo.com> Message-ID: <8763a2x4gl.fsf@sympatico.ca> On 24 Oct 2009, schonm at yahoo.com wrote: --- On Sat, 10/24/09, David Evans wrote: >> A better design would just use the parser as a front end to produce >> an intermediate representation which would be used for all the >> analysis, but the actually implementation intertwines the parsing >> and analysis much more than it should. For an IR, are you saying something like GENERIC? > Is this the approach being taken by ggcc? > http://ggcc.info/ > Perhaps an splint plugin to their frame work would be the way to go? Looking, this seems to be a global static analysis attempt. This is similar to Coverity Prevent, Polyspace verifier, etc. These use global analysis to determine thing that splint would determine through annotations. As the program determines them, there is no need to annotate, but they take significantly longer to run. I think these are significantly different? GCC has a plug-in framework in 4.5 and better. http://gcc.gnu.org/onlinedocs/gccint/Plugins.html http://gcc.gnu.org/wiki/plugins-branch However, comments (and hence splint annotations) would be discarded by the lexer. I don't believe that a plugin would have access to these (?). An alternative is to use the 'attribute' syntax to describe preconditions, postconditions and other criteria. I think that a splint plug-in for gcc would be more likely, but I am not so sure that it can't be a stand-alone program. fwiw, Bill Pringlemeir. -- I find this continuous feedback and interplay between pure mathematics and theoretical physics most fascinating. - Marco From kris.slowinski at gmail.com Mon Oct 26 02:05:37 2009 From: kris.slowinski at gmail.com (Krzysztof Slowinski) Date: Mon, 26 Oct 2009 11:05:37 +0100 Subject: [splint-discuss] pointer to pointer annotation Message-ID: <85743ff0910260305n5b4e4333r524deadb04db6427@mail.gmail.com> Hello, I have the following function declaration: void createCiphertext(char* plaintext, char**ciphertext); which is supposed to allocate memory to *ciphertext. I have a Splint warning that *ciphertext may be null and that createCiphertext needs to annotate that in the declaration, but I dont know how to annotate *ciphertext. Any help? Regards, Kris -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.cs.virginia.edu/pipermail/splint-discuss/attachments/20091026/07f213bf/attachment.html From christoph.thielecke at gmx.de Mon Oct 26 03:03:12 2009 From: christoph.thielecke at gmx.de (Christoph Thielecke) Date: Mon, 26 Oct 2009 13:03:12 +0200 Subject: [splint-discuss] splint gui: new release 0.3.3 is out Message-ID: <200910261203.12534.christoph.thielecke@gmx.de> Hello everyone, There is a new release of splintgui out which mainly is a bugfix release. Some splint options also have been added. There is also an static binary for win32 (which not requires python). Get the last version here: http://crissi.linux-administrator.com/linux/splintgui/ With best regards Christoph -- Linux User Group Wernigerode http://www.lug-wr.de/ -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 197 bytes Desc: This is a digitally signed message part. Url : http://www.cs.virginia.edu/pipermail/splint-discuss/attachments/20091026/e4782368/attachment.bin From lholzheid at bihl-wiedemann.de Mon Oct 26 11:36:55 2009 From: lholzheid at bihl-wiedemann.de (Ludolf Holzheid) Date: Mon, 26 Oct 2009 20:36:55 +0100 Subject: [splint-discuss] pointer to pointer annotation In-Reply-To: <85743ff0910260305n5b4e4333r524deadb04db6427@mail.gmail.com> References: <85743ff0910260305n5b4e4333r524deadb04db6427@mail.gmail.com> Message-ID: <20091026193655.GD3369@svr5.bihl-wiedemann.de> On Mon, 2009-10-26 11:05:37 +0100, Krzysztof Slowinski wrote: > Hello, > > I have the following function declaration: > void createCiphertext(char* plaintext, char**ciphertext); > which is supposed to allocate memory to *ciphertext. I have a Splint > warning that *ciphertext may be null and that createCiphertext needs to > annotate that in the declaration, but I > dont know how to annotate *ciphertext. As far as I remember, you have to define a char* type first, so you can write the char** as a simple pointer: typedef char *cp_t; void createCiphertext (char *plaintext, /*@null@*/ cp_t *ciphertext); HTH, Ludolf -- --------------------------------------------------------------- Ludolf Holzheid Tel: +49 621 339960 Bihl+Wiedemann GmbH Fax: +49 621 3392239 Flo?w?rthstra?e 41 e-mail: lholzheid at bihl-wiedemann.de D-68199 Mannheim, Germany --------------------------------------------------------------- From splint at sympatico.ca Mon Oct 26 13:53:58 2009 From: splint at sympatico.ca (Bill Pringlemeir) Date: Mon, 26 Oct 2009 16:53:58 -0500 Subject: [splint-discuss] pointer to pointer annotation In-Reply-To: <85743ff0910260305n5b4e4333r524deadb04db6427@mail.gmail.com> (Krzysztof Slowinski's message of "Mon, 26 Oct 2009 11:05:37 +0100") References: <85743ff0910260305n5b4e4333r524deadb04db6427@mail.gmail.com> Message-ID: <87y6mxstxl.fsf@sympatico.ca> On 26 Oct 2009, kris.slowinski at gmail.com wrote: > I have the following function declaration: void > createCiphertext(char* plaintext, char**ciphertext); which is > supposed to allocate memory to *ciphertext. I have a Splint warning > that *ciphertext may be null and that createCiphertext needs to > annotate that in the declaration, but I dont know how to annotate > *ciphertext. Any help? Does createCiphertext() have anything like this, if(ciphertext == NULL) return; You might want to check that this value is non-NULL depending on the circumstances. I don't know if this is an API that many programmers will use or if it is local to the module (in which case you should use static). Another thing is that you can easily change the API so that this error can not occur. Ie, /* returns ciphertext */ /*@only@*/ /*@null@*/ char * createCiphertext(char* plaintext); The /*@only@*/ and /*@null@*/ portions are splint annotations. Back to your original question, I am not quite sure which portion of the pointer needs to be null/non-null. I am guessing that with things the way you have them the annoation is one of, void createCiphertext(char* plaintext, /*@notnull@*/ char**ciphertext); void createCiphertext(char* plaintext, /*@null@*/ char**ciphertext); typedef /*@notnull@*/ char * good_ptr; void createCiphertext(char* plaintext, good_ptr *ciphertext); typedef /*@null@*/ char * bad_ptr; void createCiphertext(char* plaintext, bad_ptr *ciphertext); I think you have given too little context to know which version and it is better if you known what you are doing than being spoon feed. The null annotations are detailed in sections 2 of the manual. http://www.splint.org/manual/html/sec2.html http://www.splint.org/manual/html/appC.html hth, Bill Pringlemeir. -- I believe that sex is one of the most beautiful, natural, wholesome things that money can buy. - Steve Martin From splint at sympatico.ca Mon Oct 26 13:53:58 2009 From: splint at sympatico.ca (Bill Pringlemeir) Date: Mon, 26 Oct 2009 16:53:58 -0500 Subject: [splint-discuss] pointer to pointer annotation In-Reply-To: <85743ff0910260305n5b4e4333r524deadb04db6427@mail.gmail.com> (Krzysztof Slowinski's message of "Mon, 26 Oct 2009 11:05:37 +0100") References: <85743ff0910260305n5b4e4333r524deadb04db6427@mail.gmail.com> Message-ID: <87y6mxstxl.fsf@sympatico.ca> On 26 Oct 2009, kris.slowinski at gmail.com wrote: > I have the following function declaration: void > createCiphertext(char* plaintext, char**ciphertext); which is > supposed to allocate memory to *ciphertext. I have a Splint warning > that *ciphertext may be null and that createCiphertext needs to > annotate that in the declaration, but I dont know how to annotate > *ciphertext. Any help? Does createCiphertext() have anything like this, if(ciphertext == NULL) return; You might want to check that this value is non-NULL depending on the circumstances. I don't know if this is an API that many programmers will use or if it is local to the module (in which case you should use static). Another thing is that you can easily change the API so that this error can not occur. Ie, /* returns ciphertext */ /*@only@*/ /*@null@*/ char * createCiphertext(char* plaintext); The /*@only@*/ and /*@null@*/ portions are splint annotations. Back to your original question, I am not quite sure which portion of the pointer needs to be null/non-null. I am guessing that with things the way you have them the annoation is one of, void createCiphertext(char* plaintext, /*@notnull@*/ char**ciphertext); void createCiphertext(char* plaintext, /*@null@*/ char**ciphertext); typedef /*@notnull@*/ char * good_ptr; void createCiphertext(char* plaintext, good_ptr *ciphertext); typedef /*@null@*/ char * bad_ptr; void createCiphertext(char* plaintext, bad_ptr *ciphertext); I think you have given too little context to know which version and it is better if you known what you are doing than being spoon feed. The null annotations are detailed in sections 2 of the manual. http://www.splint.org/manual/html/sec2.html http://www.splint.org/manual/html/appC.html hth, Bill Pringlemeir. -- I believe that sex is one of the most beautiful, natural, wholesome things that money can buy. - Steve Martin From kris.slowinski at gmail.com Mon Oct 26 14:24:20 2009 From: kris.slowinski at gmail.com (Krzysztof Slowinski) Date: Mon, 26 Oct 2009 23:24:20 +0100 Subject: [splint-discuss] pointer to pointer annotation In-Reply-To: <87y6mxstxl.fsf@sympatico.ca> References: <85743ff0910260305n5b4e4333r524deadb04db6427@mail.gmail.com> <87y6mxstxl.fsf@sympatico.ca> Message-ID: <85743ff0910261524r283e8850vfc141764078c5d36@mail.gmail.com> I changed the version of function which returned pointer, I had null and only annotations and the warning was still reported. It is *ciphertext that can become null, I allocate the memory to it by giving the address of the original pointer as function parameter. The last version works fine for me. It is a university small project in which we are about to play with Splint. >From what I read I thought it is a frozen project, but seems like the community is working nicely. Can you tell me if Splint is used for large projects, is it useful with respect to time spent annotating and false alarms it gives ? Also, do you know any particular issues that Splint have problems to resolve (I found memory leaks with owned annotations) ? Thanks a lot for help, Kris 2009/10/26 Bill Pringlemeir > On 26 Oct 2009, kris.slowinski at gmail.com wrote: > > > I have the following function declaration: void > > createCiphertext(char* plaintext, char**ciphertext); which is > > supposed to allocate memory to *ciphertext. I have a Splint warning > > that *ciphertext may be null and that createCiphertext needs to > > annotate that in the declaration, but I dont know how to annotate > > *ciphertext. Any help? > > Does createCiphertext() have anything like this, > > if(ciphertext == NULL) > return; > > You might want to check that this value is non-NULL depending on the > circumstances. I don't know if this is an API that many programmers > will use or if it is local to the module (in which case you should use > static). > > Another thing is that you can easily change the API so that this error > can not occur. Ie, > > /* returns ciphertext */ > /*@only@*/ /*@null@*/ char * createCiphertext(char* plaintext); > > The /*@only@*/ and /*@null@*/ portions are splint annotations. > > Back to your original question, I am not quite sure which portion of > the pointer needs to be null/non-null. I am guessing that with things > the way you have them the annoation is one of, > > void > createCiphertext(char* plaintext, /*@notnull@*/ char**ciphertext); > > void > createCiphertext(char* plaintext, /*@null@*/ char**ciphertext); > > typedef /*@notnull@*/ char * good_ptr; > void createCiphertext(char* plaintext, good_ptr *ciphertext); > > typedef /*@null@*/ char * bad_ptr; > void createCiphertext(char* plaintext, bad_ptr *ciphertext); > > I think you have given too little context to know which version and it > is better if you known what you are doing than being spoon feed. > > The null annotations are detailed in sections 2 of the manual. > > http://www.splint.org/manual/html/sec2.html > http://www.splint.org/manual/html/appC.html > > hth, > Bill Pringlemeir. > > -- > I believe that sex is one of the most beautiful, natural, wholesome things > that money can buy. - Steve Martin > _______________________________________________ > splint-discuss mailing list > splint-discuss at mail.cs.virginia.edu > http://www.cs.virginia.edu/mailman/listinfo/splint-discuss > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.cs.virginia.edu/pipermail/splint-discuss/attachments/20091026/e956df82/attachment.html From Wenzel at bbr-vt.de Mon Oct 26 23:26:18 2009 From: Wenzel at bbr-vt.de (Wenzel, Bodo) Date: Tue, 27 Oct 2009 08:26:18 +0100 Subject: [splint-discuss] pointer to pointer annotation In-Reply-To: <85743ff0910261524r283e8850vfc141764078c5d36@mail.gmail.com> References: <85743ff0910260305n5b4e4333r524deadb04db6427@mail.gmail.com><87y6mxstxl.fsf@sympatico.ca> <85743ff0910261524r283e8850vfc141764078c5d36@mail.gmail.com> Message-ID: <46B6459B655D7342AB97371E8B7CD8B88D7567@sv-exch.BBR.local> Hi Kris, Not quite large projects, but it's Real Live(TM): we are using Splint on applications in embedded control which consist of some thousands lines of code. Its warnings save more time than is needed to annotate or to work around. Especially warnings about dead code, unused variables and functions, erroneous exporting, and (most important) type errors are welcome. Our sources have to be bullet-proof to external inspection. That's why we use Splint with at least "+checks +top-use +slash-slash-comment +all-macros +all-block". BTW, many warnings can be resolved by careful corrections without any annotation. For example, currently I work on a project with about 6700 LOCs, and it contains just 290 annotations of which 220 are constant declarations. If you start using Splint right from the beginning, it is no pain. Trying to make Splint happy on an existing project is something I would not try. Splint is weak in memory and array checks. We often found it reporting false, and often it does not report real errors. Arrays with more than one dimension can't be checked at all. But perhaps this is just because we don't use malloc/free in embedded control... ;-) Splint can't handle multithreading applications. This is really sad in embedded control with interrupts, or in desktop software with multiple threads. It might be solvable if Splint could be told about multiple "roots" of executions paths. Some compiler work that way to do correct overlaying of variable spaces. Cheers, Bodo -- BBR - Baudis Bergmann R?sch Verkehrstechnik GmbH Pillaustra?e 1e D - 38126 Braunschweig T: +49.531.27300-766 F: +49.531.27300-999 @: wenzel at bbr-vt.de W: http://www.bbr-vt.de Registergericht: AG Braunschweig HRB 3037 Gesch?ftsf?hrer: Dipl.-Ing. Arne Baudis Dipl.-Ing. Thomas Bergmann Dipl.-Ing. Frank-Michael R?sch USt.-ID-Nr.: DE 114 877 881