|
From: Tom H. <to...@co...> - 2012-06-08 14:36:43
|
On 08/06/12 15:29, Dan Shelton wrote:
> On 8 June 2012 16:17, Tom Hughes <to...@co...> wrote:
>> On 08/06/12 15:08, Dan Shelton wrote:
>>>
>>> On 8 June 2012 15:54, Tom Hughes <to...@co...> wrote:
>>>>
>>>> On 08/06/12 14:51, Dan Shelton wrote:
>>>>>
>>>>>
>>>>> On 31 May 2012 21:27, Tom Hughes <to...@co...> wrote:
>>>>>>
>>>>>>
>>>>>> On 31/05/12 19:45, Dan Shelton wrote:
>>>>>>
>>>>>>> This bug report just came through the AT&T AST/ksh93 development list.
>>>>>>> Can someone confirm that this is a bug, please?
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Well it's not a bug as such more a limitation of the way that
>>>>>> exp-sgcheck
>>>>>> works - there's a reason it's experimental.
>>>>>>
>>>>>> Basically exp-sgcheck assumes that once a pointer has been used to
>>>>>> access
>>>>>> one array it will always access the same array until the end of the
>>>>>> current
>>>>>> function.
>>>>>
>>>>>
>>>>>
>>>>> Is it possible to change that so that functions with variable number
>>>>> of arguments like sprintf work as expected?
>>>>
>>>>
>>>>
>>>> It's nothing to do with having a variable number of arguments, you could
>>>> get
>>>> exactly the same warning with a fixed number of arguments if you wrote a
>>>> function like this:
>>>>
>>>> void foo(char *a, char *b)
>>>> {
>>>> char *p;
>>>>
>>>> for (p = a; *p; p++)
>>>> {
>>>> ...
>>>> }
>>>>
>>>> for (p = b; *p; p++)
>>>> {
>>>> ...
>>>> }
>>>> }
>>>>
>>>> The problem is the reuse of a variable (p in this example) to access
>>>> different arrays.
>>>
>>>
>>> It can't get an option to always check the pointer for every access?
>>
>>
>> It does check it! That's the problem...
>>
>> My example above actually might work, depending on exactly what the compiler
>> does, but it is easy to construct a variant that will fail.
>>
>> The details of how sgcheck works can be found here:
>>
>> http://valgrind.org/docs/manual/sg-manual.html#sg-manual.how-works.sg-checks
>>
>> but basically, the first time an instruction is executed we remember which
>> array it accessed and then expect it to access the same array in future,
>> until the function ends anyway.
>>
>> So if the compile realised those two loops were the same and merged them
>> that code would fail - a version which had two nested loops and used p in
>> the inner loop to point to different arrays selected by the outer loop would
>> always fail.
>
> So basically you say: As soon as the compiler optimises we're doomed?
> Can a different choice of compiler (pcc ?) or disabling the optimiser
> help?
Disabling the optimiser might sometimes help - we generally recommend
using unoptimised code anyway.
Mostly though this will be triggered by code where even the high level
semantics cause a problem. An example in our code is a function with a
writev type interface like this:
void fn(const struct iovec *iov, int iovcnt)
{
int i;
for (i = 0; i < iovcnt; i++)
{
void *buffer = iov[i].iov_base;
int length = iov[i].iov_len;
... do stuff with buffer ...
}
}
because the body of that loop uses the same instructions to operate on
different arrays accessed by indexing iov you run into this problem.
>>>> And no, we know of no good solution.
>>>>
>>>> Basically exp-sgcheck was an interesting experiment, but in my experience
>>>> it
>>>> is not workable for real world programs.
>>>
>>>
>>> Is there any tool based on valgrind which can do checks on global
>>> arrays and stack variables and is not experimental?
>>
>>
>> No, because this is basically a research grade problem that is currently (to
>> my knowledge unsolved) as to how to do such checks on an unmodified program.
>
> Why does Purify (your closest competitor AFAIK) handle this right?
Because it works at link time to modify the code and insert canary words
between stack items I believe.
Tom
--
Tom Hughes (to...@co...)
http://compton.nu/
|