That's the users responsibility, not one the author of the library should
concern himself with. If the user passes crap to the library, a crash (or
at least a SIGSEGV) is what's called for.
The alternative is requiring complete checking of any pointer passed to any
library, thus penalizing those programs that pass valid pointers for the
benefit of programmers who can't be bothered to ensure their pointers are
valid.
That's not the proper way to do it.
-------------------------------------------------------------------------------
___________________________
< Yow! Am I having fun yet? >
---------------------------
\
\
>> If you need code to check whether or not a pointer is valid, _your code_
>> is fundamentally flawed.
>
> Suppose a library that receives a bad pointer. Isn't it reasonable to
> check its validity before using it?
Only if such a check exists. Usually it doesn't.
It isn't the pointers which point at unmapped address space that are the
problem; those produce a nice clean segfault. The real problem is with
pointers which point at something they're not supposed to be pointing at,
which end up silently trashing data. And there's no way to detect that.
If you want that level of hand-holding, you need to use a high-level
language which simply doesn't admit the possibility of an invalid pointer.
Not if you're implementing a library interface. There is no security
boundary between a library function and its caller. Within a single
process, if any part of it is malicious, the whole thing is malicious.
If you want to be able to classify one piece of code as an attacker and
another as its potential victim, they need to be in separate processes.
With different user IDs.
--
Alan Curry
>On Sun, 18 Sep 2011 00:57:32 +0200, jacob navia wrote:
>
>> Le 18/09/11 00:38, Harald van Dijk a écrit :
>>> On Sep 18, 12:29 am, jacob navia<ja...@spamsink.net> wrote:
>>>> In a recent discussion about preconditions, I argued that testing ALL
>>>> preconditions would be unpractical. As an example of a precondition
>>>> impossible to test I presented the problem to know if a pointer points
>>>> to a really readable place in memory.
>>>>
>>>> The windows API provides the function bool IsBadReadPtr(const void
>>>> *lp, size_t ucb);
>>>>
>>>> This takes a pointer and a size and returns true if it is OK, zero if
>>>> it fails.
>>>>
>>>> Problem is, that is only present under windows.
>>>
>>> That is not its biggest problem. Even on Windows, don't use it. Please
>>> read
>>> <http://blogs.msdn.com/b/oldnewthing/archive/2006/09/27/773741.aspx>
>>> for reasons why the concept of IsBadReadPtr (and IsBadWritePtr even
>>> more so) is fundamentally flawed.
>>
>> They aren't "flawed".
>
>If you need code to check whether or not a pointer is valid, _your code_
>is fundamentally flawed.
Any language in which it is possible for a pointer to be invalid but
which provides no way to test for validity is fundamentally flawed.
What existing language has pointers and is not "fundamentally flawed"?
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
--
Joe Wright
"If you rob Peter to pay Paul you can depend on the support of Paul."
> In article <H7idnUSmaqgcL-vT...@giganews.com>,
> Joe Wright <joeww...@comcast.net> wrote:
>>On 9/18/2011 20:32, Keith Thompson wrote:
>>> c...@tiac.net (Richard Harter) writes:
>>> [...]
>>>> Any language in which it is possible for a pointer to be invalid but
>>>> which provides no way to test for validity is fundamentally flawed.
>>>
>>> What existing language has pointers and is not "fundamentally flawed"?
>>>
>>Indeed. Testing a pointer by simple inspection can tell you whether it is
>>null or not. If it is null it is not valid. If not you simply can't tell.
>
> We just keep going around and around on this.
>
> It is perfectly obvious that it is possible to design and implement a
> language in which pointers (or something resembling what we call pointers in
> C) are safe. But that language won't be C.
And in which those "pointers" have semantics somewhat different from
what C calls pointers. And, I expect, semantics somewhat different from
what most readers of this newsgroup infer from the word pointers.
>c...@tiac.net (Richard Harter) writes:
>[...]
>> Any language in which it is possible for a pointer to be invalid but
>> which provides no way to test for validity is fundamentally flawed.
>
>What existing language has pointers and is not "fundamentally flawed"?
Please do not snip the relevant text, i.e.
>>>If you need code to check whether or not a pointer is valid, _your code_
>>>is fundamentally flawed.
>>
>> Any language in which it is possible for a pointer to be invalid but
>> which provides no way to test for validity is fundamentally flawed.
I was making a (mildly sarcastic) point about the statement I was
commenting on.
That said, I dunno off hand about languages that have pointers and
aren't fundamentally flawed. It depends on what counts as pointers.
If "pointer" means "address" you're out of luck. Once you get into
the world of smart pointers and references it's a different matter.
The interesting thing is that it isn't hard for a language to have
references that can be tested for validity.
>c...@tiac.net (Richard Harter) writes:
Fair enough, if those are your only choices. Quite often, however,
the cost of verification is insignificant. Choosing the *fast*
library could be a premature optimization. Now if I actually had two
libraries that did the same thing *and* I was really really concerned
with speed *and* I did performance measurements on both *and* there a
measurable difference, then I might go with the one that doesn't
verify its inputs. How often does that happen?
That's normally a case of prevention by controlling what can be be used
to initialise a reference rather than by detection.
--
Ian Collins
That may be - I think that's what fortran does. But that's only half
of it; you need to be able to detect whether a reference is stale.
That's a trifle more complicated.
What you really mean is "too low level" rather than "fundamentally
flawed". At some point you've got to write to raw addresses. C allows
you to pass these around, and makes it difficult to tag them with
range and type information, either at the level of the compiler or in
client code. That's the feature that makes C what it is. If you move
to C++ you can use controlled sequences, and essentially eliminate
pointers. But experience shows that this brings its own problems.
--
Fuzzy logic trees, now in Apple ebooks
http://www.malcolmmclean.site11.com/www
Not really. Besides checking for NULL [*] pointers it's up to the
caller to pass valid pointers since they're not really easily testable
[hence this thread] in a portable fashion.
> You should have a way to avoid crashes because of malicious code that
> feeds you a bad pointer isn't it?
>
> Besides, my motivation here is that in principle I thought that this
> would be impossible, but later on and reflecting a bit, I found out
> that it is not that difficult. I am not advocating the usage of this
> function everywhere.
Raising a signal is not the best of ideas because you could be in a
debugger in which signals are masked to the user process and throw
debugging problems.
[*] I check for NULL pointers since I tend to use memset/calloc and it
lets me find any uninitialized pointers easily.
Tom
I guess that common sense is on the table, based on your
response. Your original statement was very broad and, to my
mind, overreaching. Now that you've qualified it, it makes more
sense.
--
"Some people *are* arrogant, and others read the FAQ."
--Chris Dollin
The phrase "valid pointer" is context-dependent. NULL is not valid
as the operand of the unary "*" operator; it's perfectly valid as
the argument of free().
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
"Keith Thompson" <ks...@mib.org> wrote in message
news:lnmxe05...@nuthaus.mib.org...
> "BartC" <b...@freeuk.com> writes:
>> "Ben Pfaff" <b...@cs.stanford.edu> wrote in message
>> news:87zki0w...@blp.benpfaff.org...
>>
>>> It's pretty easy to come up with examples of functions that are
>>> trivial if you don't check the arguments and nontrivial if you
>>> do. An excerpt from a library of mine is below. Each of these
>>> functions is only one or two machine instructions when inlined.
>>
>> The body of these functions is so trivial that one wonders why they
>> aren't
>> written in-line anyway, or at least wrapped in a macro.
>
> Writing them in-line would be more error-prone. Making them functions
> lets you give each operation a name.
>
> How would a macro be better than an inline function?
Looking at the original functions, they are just applying some
abstraction/hiding, so are doing exactly what macros are for.
Written as functions, they are not guaranteed to be inline. And some
overzealous maintainer might come along and decide the pointer arguments
need to be validated...
--
Bartc
Actually, that's not entirely true. I use macros to access generic
containers with void* where the type information is passed on to
another function that uses 'sizeof (type)'.
\code snippet
void* gc_array_front( struct c_array* array )
{
void* p = NULL;
if ( array->size ) {
p = array->buffer;
}
return p;
}
#define c_array_front( array, type ) ( (type*)
(gc_array_front( (array) )) )
\end snippet
If I store the 'sizeof (type)' in the array structure itself, it's
possible to assert that the internal element size assigned when the
array was allocated matches the size of the type used in the access
function.
\code snippet
void* gc_array_front( struct c_array* array, size_t size )
{
void* p = NULL;
c_return_value_if_fail( array != NULL, NULL );
c_return_value_if_fail( size == array->element_size, NULL );
if ( array->size ) {
p = array->buffer;
}
return p;
}
#define c_array_front( array, type ) ( (type*)
(gc_array_front( (array), sizeof (type) )) )
\endcode
This can generate a constraint violation for c_array_front( ar, char )
if the original container array contains objects of type 'double', but
it cannot distinguish between invalid casting between 'int' and
'float' (if 'sizeof (int) == sizeof (float)').
It's a very special case though :-)
in the everyday case it could be O(1) because memory for functions
is released as stack
could be patological O(numberPonters) cases for global memory
or if the memory not follow the stack model
> but i can think on that we want O(1)
> so something using hash function
so wrong above
Yes, sure. You see two arguments. Are the pointers bad? The first comes
from an argument to this function, where were that created?
Up the stack.
Get the docs for the call to the library. Ahhh the two arguments
look ok... Maybe this is the consequence of a bug I corrected yesterday.
Let's come back to the situation before those changes.
Pull that version. Ahh Crash also, it wasn't that.
Let's look better at those documentation for that dammed library.
Ahhhh the arguments are inversed damm it!
I found it after 1 lost day. Well, that is developing.
>> 2) When you pass a bad pointer the library opens a dialog box:
>> "Invalid argument to function Library_input(), argument two"
>
> If the library already invoked undefined behavior (by crashing)
> the state of your program is also undefined and opening a dialog
> box may well result in another crash, thus hiding the details of
> the original crash and preventing debugging most effectively.
>
No. There isn't (precisely) any crash. The library cleanly reports a
failure in your program.
> I would, personally, object to using any library that does that.
>
>> You see?
>
> Nope.
>
Of course, you like software that crashes like that. OK.
>> A crash isn't always a good thing.
>
> A crash is never a good thing, but it's preferable to continuing
> in an undefined state.
>
Maybe, maybe not. It depends on the importance of the library in the
software.
For instance, if you are doing a GPS appplication, a crash in the
graphics module that scrolls the map is not that important,
the GPS can continue to work... The main application is a module
that warns the driver if he/she goes beyond the speed limit for the
road. The map is just "to be nice".