ptrs validity

A

a

Hi,
I have a pointer that points to an unknown heap memory block, is it possible
to check the pointer + 3 is valid or not?
If it is impossible, how can I do the check?
Thanks
 
R

Richard Heathfield

a said:
Hi,
I have a pointer that points to an unknown heap memory block, is it
possible to check the pointer + 3 is valid or not?
No.

If it is impossible, how can I do the check?

You can't. It's impossible.
 
R

Richard Bos

a said:
I have a pointer that points to an unknown heap memory block, is it possible
to check the pointer + 3 is valid or not?
No.

If it is impossible, how can I do the check?

If it is impossible, it is impossible.

Richard
 
J

jacob navia

a a écrit :
Hi,
I have a pointer that points to an unknown heap memory block, is it possible
to check the pointer + 3 is valid or not?
If it is impossible, how can I do the check?
Thanks

It depends on the operating system.

Under the windows OS you can use:

IsBadReadPtr(ptr, size)

in your case would be

IsBadReadPtr(ptr,3);

Other operating systems maybe have other methods.

jacob
 
K

Keith Thompson

jacob navia said:
a a écrit :

It depends on the operating system.

Under the windows OS you can use:

IsBadReadPtr(ptr, size)

in your case would be

IsBadReadPtr(ptr,3);

Other operating systems maybe have other methods.

Or, more likely, they don't.

The trick is to keep track of this kind of information yourself. You
knew how big the pointed-to object was when you allocated it. (Unless
it was allocated in code that you don't control; in that case, things
can be a bit more complicated.)
 
R

Richard Bos

jacob navia said:
a a écrit :

It depends on the operating system.

Under the windows OS you can use:

IsBadReadPtr(ptr, size)

in your case would be

IsBadReadPtr(ptr,3);

jacob demonstrating once more why off-topic is off-topic:

_Often_ you can use that function under MS Windows. Not always. Not that
I expect Mr. navia to understand this, but one has to cater for the
educatable newbies, doesn't one.

Also, the example as given doesn't answer the question as asked, but
I'll leave the reason for that as an exercise for the reader.
Other operating systems maybe have other methods.

Or perhaps not.

In any case, if you need to know this, you haven't done your bookkeeping
properly. You should remember how large your allocated blocks of memory
are; and if a function requires memory of a certain size, make sure that
memory passed to it is that size. Making sure of this up front is
usually a lot easier than patching up the problems when you get it
wrong, too.

Richard
 
F

Frederick Gotham

a posted:
Hi,
I have a pointer that points to an unknown heap memory block, is it
possible to check the pointer + 3 is valid or not?
If it is impossible, how can I do the check?
Thanks


Can't be done using "conventional" means. However, if you're willing to get
your hands dirty...

(CAUTION: Bad advice starts here.)


Hijack "malloc" and keep a track of what memory is allocated, something
like:

#define malloc mallocINTERNAL

#include "stdlib.h"

#undef malloc

void *malloc( size_t const len )
{
void *p = mallocINTERNAL(len);

/* Now access something like a
linked list or a look-up table */
}


Then you could define a function which tells you whether a byte is valid:

void ValByte(char*);
 
A

Ancient_Hacker

a said:
Hi,
I have a pointer that points to an unknown heap memory block, is it possible
to check the pointer + 3 is valid or not?
If it is impossible, how can I do the check?
Thanks

The language-lawyers will give you the disengenuous answer "No, it's
impossible kid, go away, you bother us".

Here's ELEVEN different ways to do it:

if by "valid" you mean "inside addressable memory space" you can

(1) On Unix, set up a SEGFAULT signal handler to trap bad memory
references.
(2) On most systems that have exception handling try/catch, you can
usually catch address exceptions.
(3) On Windows, and I suspect Unix/Linux, you can ask the OS for a list
of memory segments allocated to your process, and their attributes.
Search the list to see if the desired address lands inside a readble
or writeable area.

(4) On Windows, there's a APi for this, IsBadPtr() or somesuch? Or
was this only for Win16 style segments? I forget

(5) On the x86 architecture, since the 486, there's a hardware
instruction to check this, ERRR, ERRW, ERRE to check for read write or
execute addressability of a pointer.
If your C compiler can do an _emit or _asm{} block, you can use this
for a very quick, definitive and encvapsulated answer.

(6) Most linkers emit dummy tags, something like _endBSS, _endCODE,
_endDATA, symbols you can check at run-time to see if an address falls
in a particular range.

(7) Most heap implementations expose a structure with heap info, so
you can access arena->base, arena->limit, and other interesting
heap-address revealing pointers.

(8) Keep a list of all malloc()'ed blocks, this is very useful for
checking parameters and pointers and values passed to free() and
realloc() for validity.

(9) Put all your globals in a struct, so you can check addresses
against the ends of that struct for validity.

(10) On the x86 and many other architectures, you can define malloc()
to allocate a fresh, hardware checked segment for each allocation. Then
there's a way to lookup the base and limit of each segment in the
segment tables. Foolproof and free hardware array bounds checking!

(11) Redefine malloc() to pad each heap block and all unallocated
memory before and after each block and arena and unused stack with a
run of 0xDEADBEEF. if p+3 == 0xDEADBEEF you know you're addressing
past the end of a heap block.
 
R

Richard Heathfield

Ancient_Hacker said:
The language-lawyers will give you the disengenuous answer "No, it's
impossible kid, go away, you bother us".

Well, I'll buy the "no, it's impossible" part of that parody, sure. And I
certainly applaud your efforts to overcome the limitations of the language
definition in an attempt to provide a useful answer. Nevertheless...
Here's ELEVEN different ways to do it:

if by "valid" you mean "inside addressable memory space" you can

(1) On Unix, set up a SEGFAULT signal handler to trap bad memory
references.

Not only did the OP not specify Unix, but this is not guaranteed to work
even on that platform. For example, the library might allocate page-sized
blocks. If so, allocating a three-byte block would result in p + 3 being
invalid in C language terms but acceptable to the OS (but
comp.unix.programmer would know more about that). I just tested this by
allocating three bytes and writing to all four of them (admittedly on Linux
rather than Unix), and the write did not cause a segfault.

(2) On most systems that have exception handling try/catch, you can
usually catch address exceptions.

C doesn't have try/catch.
(3) On Windows, and I suspect Unix/Linux, you can ask the OS for a list
of memory segments allocated to your process, and their attributes.
Search the list to see if the desired address lands inside a readble
or writeable area.

How are you going to do that in a portable manner, though? The OP posted in
comp.lang.c, which suggests he wants an answer in C language terms, not a
system call which will vary from system to system.
(4) On Windows, there's a APi for this, IsBadPtr() or somesuch? Or
was this only for Win16 style segments? I forget

Right. I forget too. Which is why we refer such questions to
comp.os.ms-windows.programmer.win32 - where they are far more likely to
know the right answer.
(5) On the x86 architecture, since the 486, there's a hardware
instruction to check this, ERRR, ERRW, ERRE to check for read write or
execute addressability of a pointer.
If your C compiler can do an _emit or _asm{} block, you can use this
for a very quick, definitive and encvapsulated answer.

But the OP did not indicate that he is using an x86.
(6) Most linkers emit dummy tags, something like _endBSS, _endCODE,
_endDATA, symbols you can check at run-time to see if an address falls
in a particular range.

Does that include the implementations used on or for:

* The Mac?
* The 360 series?
* Unisys boxes?
* Concurrents?
* SHARCs?
* Cybers?
(etc)
(7) Most heap implementations expose a structure with heap info, so
you can access arena->base, arena->limit, and other interesting
heap-address revealing pointers.

See (6).
(8) Keep a list of all malloc()'ed blocks, this is very useful for
checking parameters and pointers and values passed to free() and
realloc() for validity.

This is perhaps the most portable and practical suggestion - basically
wrapping malloc with a memory accounting system. And it demonstrates that
our initial answer ("it's impossible") is actually wrong. It /can/ be done
if you're prepared to throw enough work into it, and provided everyone uses
the wrapper, and provided you recognise that it will only handle malloc'd
memory (as opposed to automatic objects) - but that's okay, because it's
all the OP asked for. Nevertheless, if someone else on the team calls
malloc directly rather than going through your wrapper, the method fails.
(9) Put all your globals in a struct, so you can check addresses
against the ends of that struct for validity.

And if the OP isn't using globals? I don't get this one at all.
(10) On the x86 and many other architectures, you can define malloc()
to allocate a fresh, hardware checked segment for each allocation. Then
there's a way to lookup the base and limit of each segment in the
segment tables. Foolproof and free hardware array bounds checking!

This code must run unmodified on the N4242, due Real Soon Now, for which the
hardware specs are not yet available. Suddenly this technique isn't so
foolproof.
(11) Redefine malloc() to pad each heap block and all unallocated
memory before and after each block and arena and unused stack with a
run of 0xDEADBEEF. if p+3 == 0xDEADBEEF you know you're addressing
past the end of a heap block.

And what if p+3 == 0xD29102933? Can you guarantee that p+3 is valid simply
because it is not 0xDEADBEEF?
 
D

David Resnick

a said:
Hi,
I have a pointer that points to an unknown heap memory block, is it possible
to check the pointer + 3 is valid or not?
If it is impossible, how can I do the check?
Thanks

As others have said, this isn't possible in portable C. In particular,
if it is "unknown heap memory", that means you can't have kept track of
it by, as suggested elsethread, by wrapping *alloc and doing some
bookkeeping. If you have lots of allocations, even if you do do the
bookkeeping there is quite a bit of overhead involved if you check
pointers often.

The question that comes to me is why you want to do this? I'd suggest
that if you want to see if your program is using invalid pointers you
use one of the many tools available. Depending on your platform, you
could look into what tools like valgrind/dmalloc/electric
fence/purify/etc can tell you about misuse of pointers. If you have
questions about these tools, you should take them to a group dedicated
to your operating system, as they only work on a limited set of
operating systems, and the same tools may work differently on the
different systems anyway...

-David
 
K

Kenneth Brody

Richard said:
Ancient_Hacker said:
Hi,
I have a pointer that points to an unknown heap memory block, is it
possible to check the pointer + 3 is valid or not?
If it is impossible, how can I do the check?
Thanks
[...]
(8) Keep a list of all malloc()'ed blocks, this is very useful for
checking parameters and pointers and values passed to free() and
realloc() for validity.

This is perhaps the most portable and practical suggestion - basically
wrapping malloc with a memory accounting system. And it demonstrates that
our initial answer ("it's impossible") is actually wrong. It /can/ be done
if you're prepared to throw enough work into it, and provided everyone uses
the wrapper, and provided you recognise that it will only handle malloc'd
memory (as opposed to automatic objects) - but that's okay, because it's
all the OP asked for. Nevertheless, if someone else on the team calls
malloc directly rather than going through your wrapper, the method fails.

That's why you should call the function something along the lines of
WasThisPointerAllocatedViaMyMallocWrapper(), rather than IsPtrValid().

:)

[...]

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
A

Al Balmer

a posted:



Can't be done using "conventional" means. However, if you're willing to get
your hands dirty...

(CAUTION: Bad advice starts here.)
Agreed.


Hijack "malloc" and keep a track of what memory is allocated, something
like:
There's no need to "hijack" malloc to keep track of what memory is
allocate. Just keep track.
 
A

Al Balmer

This is perhaps the most portable and practical suggestion - basically
wrapping malloc with a memory accounting system. And it demonstrates that
our initial answer ("it's impossible") is actually wrong. It /can/ be done
if you're prepared to throw enough work into it, and provided everyone uses
the wrapper, and provided you recognise that it will only handle malloc'd
memory (as opposed to automatic objects) - but that's okay, because it's
all the OP asked for. Nevertheless, if someone else on the team calls
malloc directly rather than going through your wrapper, the method fails.
I can see situations where this might be useful, but in general, it
isn't needed, because other factors constrain the use of the allocated
space anyway. For example, when you allocate space to contain an array
of known size - it's easier just to make sure your array index never
gets out of range than to fool around with a list of allocated blocks.
The only time I've had a need for a malloc-wrapping (actually
replacement) method is in debugging, when the facility was provided by
third-party libraries. I haven't actually used such a package since
the DOS days.
 
A

Ancient_Hacker

Richard said:
Not only did the OP not specify Unix, but this is not guaranteed to work
even on that platform. For example, the library might allocate page-sized
blocks. If so, allocating a three-byte block would result in p + 3 being
invalid in C language terms but acceptable to the OS (but
comp.unix.programmer would know more about that). I just tested this by
allocating three bytes and writing to all four of them (admittedly on Linux
rather than Unix), and the write did not cause a segfault.

We don't know exactly what the OP meant by "valid", but let me guess
Usually when people ask about accessing A+3, they intend to use 32-bit
instructions to manipulate 8-bit data, sometimes with pre-fetch at the
end . A very common case is CRC-ing a network packet, which can be
done very speedily if you allow a little slop. Same with some
pattern-matching operations.

Which means the last time thru the loop the code might pre-fetch up to
3 bytes past the end of data. So all they might want to know is if the
memory is readable without major kabooms.

There isnt a way I know of in the C language to do this, but if you'll
lower yourself to allow a portability hazard....

C doesn't have try/catch.

Well, disingenous at best. The two most common C compilers, gcc and vc
which together cover maybe 80% of the market, DO have try and catch.

How are you going to do that in a portable manner, though? The OP posted in
comp.lang.c, which suggests he wants an answer in C language terms, not a
system call which will vary from system to system.

Well, for gnu and vc IIRC , you need abotu 7 lines of codee, just read
the map file and look for ".data 0x..........."

But the OP did not indicate that he is using an x86.

Seeing as that smelly architecture has more copies out there than
anything else, there's a good chance it meets the OP's needs.
Does that include the implementations used on or for:

* The Mac?
* The 360 series?
* Unisys boxes?
* Concurrents?
* SHARCs?
* Cybers?

very curious that you mention company names, instead of linker names.
The name of the ciompany has nothing to do with the linker.
All the above except for the 60-bit Cybers can run Linux and gcc and
the gcc linker.

Even on other OS's, it's nearly trivial to link in two little stubs
"low.a" and "high.a", one as the first object file, the other as the
last object file, thereby defining the beginning and end symbols for
the rare linker that doe4snt provide this information as link symbols
or in the link map file.

I don't know of a working C implementation for the 60-bit Cybers.
This code must run unmodified on the N4242, due Real Soon Now, for which the
hardware specs are not yet available. Suddenly this technique isn't so
foolproof.

Yep, it's a non-portable technique. Moving the code to a new system
might take, oh, two hours to rename a few API calls. Once that's done
all the bad pointers just jump out at you.

Versus stewing (as I have) for months trying to find unset pointers.

]
You decide whether it's worth porting the code.

And what if p+3 == 0xD29102933? Can you guarantee that p+3 is valid simply
because it is not 0xDEADBEEF?

.... right... it's not foolproof, but it does catch at least 3/4 the
problems. If you see DEADBEEF you know it's (probably) unused heap,
which depending on your point of view is valid (for just reading) or
invalid (for writing). if p+3 isnt DEADBEEF, well, you obviously can
read it.... writing ti may be bad.

Programming involves a lot of analog value judgements. Is it better to
catch 3/4 of the problems, or just claim it's impossible?

Is it okay to save a plane crashing by using a feature that has been
in 92% of the C compilers out there for a handful of years, even though
it's not in any standard, or do we just buy a flower-farm to send to
funerals?

Is it better to spend 2 hrs porting "non-portable" code, or wonder
forever if there's some random memory reference somewhere?

Do we give up, just because the Cyber loader which hasnt been run in
60-bit mode for over 15 years doesnt emit _End_DATA tags, or do we
document that it works on 88.8% of the systems out there?

Things arent always black and white. Many times a little openness to
shades of gray can be very helpful.
 
R

Richard Heathfield

Ancient_Hacker said:
We don't know exactly what the OP meant by "valid",

If it points to an existing object or function, it's valid. Otherwise, it
isn't.
but let me guess

I prefer not to guess.

Well, disingenous at best.

No, C doesn't have try/catch - full stop.
The two most common C compilers, gcc and vc
which together cover maybe 80% of the market, DO have try and catch.

Not when invoked in conforming mode, which is the only mode we're really
concerned with in clc.

Well, for gnu and vc IIRC , you need abotu 7 lines of codee, just read
the map file and look for ".data 0x..........."

All the world's Linux/Windows, hmmm? Well, actually the world is a lot
bigger than that.

Seeing as that smelly architecture has more copies out there than
anything else, there's a good chance it meets the OP's needs.

If that is true, he'll get a better answer in comp.os.ms-dos.programmer or
comp.os.ms-windows.programmer.win32 or comp.os.linux.development.apps where
the platform-specific experts hang out.
very curious that you mention company names, instead of linker names.

The name of the ciompany has nothing to do with the linker.

And a lowly programmer typically has little or no say about which linker is
to be used on a particular platform.
All the above except for the 60-bit Cybers can run Linux and gcc and
the gcc linker.

Doesn't mean they /do/, though. I've worked on a variety of architectures
over the last 15 years, and the only ones I've met where gcc was being used
were Sparcs and x86s. Sure, it's nice to know that gcc can run on a
mainframe, but all too often it's actually running C/370 or LE 370 or some
such cruft.

Yep, it's a non-portable technique. Moving the code to a new system
might take, oh, two hours to rename a few API calls. Once that's done
all the bad pointers just jump out at you.

There's a far easier way to make them jump out. Assign NULL to them.

T *p = NULL; /* give p a known-invalid value, unless you know... */
FILE *fp = fopen("foo.txt", "w"); /* ... what value to give it */

if(fp != NULL)
{
fprintf(fp, "Hello, foo\n"); /* after use... */
fclose(fp); /* ...release the resource... */
fp = NULL; /* ...and invalidate the pointer */

You decide whether it's worth porting the code.

Okay. I decide it isn't. You might decide differently, of course. That's up
to you.

... right... it's not foolproof, but it does catch at least 3/4 the
problems.

Unlikely. Checking if(p + 3 == 0xDEADBEEF) is only likely to catch around
1/4000000000 of the problems.
Programming involves a lot of analog value judgements. Is it better to
catch 3/4 of the problems, or just claim it's impossible?

When you define a pointer, you know whether it's valid. Don't forget.
Following this strategy solves way more than 3/4 of the problems.

<snip>
 
K

Keith Thompson

Ancient_Hacker said:
Richard Heathfield wrote:
[...]
[attribution lost]
Well, disingenous at best. The two most common C compilers, gcc and vc
which together cover maybe 80% of the market, DO have try and catch.

Incorrect.

gcc is actually a collection of compilers for several different
languages. The gcc C compiler does not, as far as I know, implement
try and catch as an extension to the C language. The gcc C++ compiler
does, of course, implement try and catch -- but that's because it's a
C++ compiler. I'm guessing the same applies to vc.
 
F

Flash Gordon

Keith said:
Ancient_Hacker said:
Richard Heathfield wrote:
[...]
[attribution lost]
Well, disingenous at best. The two most common C compilers, gcc and vc
which together cover maybe 80% of the market, DO have try and catch.

Incorrect.

gcc is actually a collection of compilers for several different
languages. The gcc C compiler does not, as far as I know, implement
try and catch as an extension to the C language. The gcc C++ compiler
does, of course, implement try and catch -- but that's because it's a
C++ compiler. I'm guessing the same applies to vc.

Actually, MS VC++ implements _try as an extension to C. However, I
believe you are correct about gcc.
 
A

Ancient_Hacker

Keith said:
"Ancient_Hacker" <[email protected]> writes:
The two most common C compilers, gcc and vc
gcc is actually a collection of compilers for several different
languages.

Nice hair-splitting. When you type "gcc", what compiler do you get?


The gcc C compiler does not, as far as I know, implement
try and catch as an extension to the C language.

It has since version 3.3, June 2003. We're now in July, 2006, at
version 4.1. Your info is about three years out of date.


I'm guessing the same applies to vc.

Nice try, but some of us have VC and don't have to guess and get the
facts right.
 
B

Ben Pfaff

Ancient_Hacker said:
It has since version 3.3, June 2003. We're now in July, 2006, at
version 4.1. Your info is about three years out of date.

Can you cite a section of the GCC manual that talks about try and
catch in a C context? I don't see anything about it in the "C
Extensions" chapter, which is the obvious place for it. I do
see some references in an Objective C or C++ context, but nothing
related to C.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top