How to transfer an address value without using pointers

S

somenath

somenath said:
On Jun 18, 4:54 pm, Ben Bacarisse <[email protected]> wrote:
#include <stdio.h>
#include <stdlib.h>
void send(char *str);
int main(void)
{
     char s[512];
     sprintf(s, "%p", malloc(1024));
     send(s);
     return 0;
}
void send(char *str)
{
     void *p;
     sscanf(str, "%p", &p);
     free(p);
}
Could you please explain why it won’t show undefined behavior?
When I ran this code I get
Segmentation fault (core dumped).

Exactly the code above gives you a segmentation fault?  If so, what
compiler it it?  I can only point to what the standard says about the
%p format which is that you can convert a pointer to text and back
again.

I am running the bellow code

$ cat simple.c
#include <stdio.h>
#include <stdlib.h>

void send(char *str);

int main(void)
{
char s[512];
sprintf(s, "p", malloc(1024));
send(s);
return 0;



}


void send(char *str)
{
void *p;
sscanf(str, "%p", &p);
free(p);


}

I think I missed the % in sprintf(s, "p", malloc(1024));

I am using
gcc version 3.3.1 (cygming special)
 
S

santosh

somenath said:
somenath said:
On Jun 18, 4:54 pm, Ben Bacarisse <[email protected]> wrote:
#include <stdio.h>
#include <stdlib.h>
void send(char *str);
int main(void)
{
char s[512];
sprintf(s, "%p", malloc(1024));
send(s);
return 0;

void send(char *str)
{
void *p;
sscanf(str, "%p", &p);
free(p);
Could you please explain why it won?t show undefined behavior?
When I ran this code I get
Segmentation fault (core dumped).

Exactly the code above gives you a segmentation fault?  If so, what
compiler it it?  I can only point to what the standard says about the
%p format which is that you can convert a pointer to text and back
again.
I am running the bellow code

$ cat simple.c
#include <stdio.h>
#include <stdlib.h>
void send(char *str);
int main(void)
{
char s[512];
sprintf(s, "p", malloc(1024));
send(s);
return 0;
}
void send(char *str)
{
void *p;
sscanf(str, "%p", &p);
free(p);
}

I think I missed the % in sprintf(s, "p", malloc(1024));

So you knew what the problem was, yet you chose to post that Ben's code
did not work, without fixing your introduced bug?

<snip>
 
V

vippstar

@gmail.com wrote:
int rc;
char s[512];
rc = snprintf(s, sizeof s, "%p", (void *)s);
Or with a VLA:
char ptr[snprintf(NULL, 0, "%p", (void *)valid_ptr)+1];
No, it is not guaranteed that the text representation of a pointer is
less than 65534 bytes.
(ISO C99 TC3, 5.2.4.1 - Environmental limits)
Nor is it guaranteed that an int is less than any fixed number of
bytes. A conforming implementation can reject *every* program that uses
objects of type int that would be strictly conforming on other
implementations. But
I don't see how a conforming implementation can reject every program
that uses int.
Do you mean that,
int main(void) { int i = 0; return i; } Is allowed to be rejected by a
conforming implementation? How so?

Yes: if sizeof(int) > 65535, then this program exceeds the environmental
limit you mentioned.
I don't think you understand. I did not talk about sizeof (pointer)
(or sizeof (int)). I talked about the text representation of the
pointer, ie what sprintf() would write to the buffer with the 'p'
conversion specifier.
If sizeof (int) > 65535, nothing is wrong, especially not in my
example program.
Okay, I can see that: if it is more, then the implementation cannot meet
the requirements for snprintf's return value.


I'm not sure what you mean here. Could you explain a bit more?
I'm just trying to give an example of what sprintf() is not allowed to
do. You agreed before when I said that the text representation of %p
is not more than the hosts INT_MAX, so the example is not needed. I'm
usually bad at trying to prove a point with examples.
Out-of-range conversions between integer types don't cause the behaviour
to be undefined.
AFAIK they do with signed integers, but I could be wrong so I'd
appreciate of you or someone else could point me to the section of the
standard which explains what happends.
Even if there really isn't a problem, the resulting value would be
negative, right? Which means sprintf() would return a negative value
without an error occuring, which the function is not allowed to.

<snip>
 
S

somenath

somenath said:
<snip>
#include <stdio.h>
#include <stdlib.h>
void send(char *str);
int main(void)
{
char s[512];
sprintf(s, "%p", malloc(1024));
send(s);
return 0;
}
void send(char *str)
{
void *p;
sscanf(str, "%p", &p);
free(p);
}
<snip>
Could you please explain why it won?t show undefined behavior?
When I ran this code I get
Segmentation fault (core dumped).
Exactly the code above gives you a segmentation fault?  If so, what
compiler it it?  I can only point to what the standard says about the
%p format which is that you can convert a pointer to text and back
again.
I am running the bellow code
$ cat simple.c
#include <stdio.h>
#include <stdlib.h>
void send(char *str);
int main(void)
{
        char s[512];
        sprintf(s, "p", malloc(1024));
        send(s);
        return 0;
}
void send(char *str)
{
        void *p;
        sscanf(str, "%p", &p);
        free(p);
}
I think I missed the % in  sprintf(s, "p", malloc(1024));

So you knew what the problem was, yet you chose to post that Ben's code
did not work, without fixing your introduced bug?


Sorry for all the confusion created by me. But If you look back it
was not
Ben Bacarisse ‘s code I was referring. At the beginning I was
referring to “vipps” code which did not have %p in sprintf.I did the
mistake by not considering the Ben Bacarisse ‘s correction.

I am very sorry for this.
 
B

Ben Bacarisse

On Jun 19, 8:16 am, Harald van Dijk <[email protected]> wrote:
AFAIK they do with signed integers, but I could be wrong so I'd
appreciate of you or someone else could point me to the section of the
standard which explains what happends.

I'll limit my reply to this safe ground:

6.3.1.3 Signed and unsigned integers

1 When a value with integer type is converted to another integer type
other than _Bool, if the value can be represented by the new type,
it is unchanged.

2 Otherwise, if the new type is unsigned, the value is converted by
repeatedly adding or subtracting one more than the maximum value
that can be represented in the new type until the value is in the
range of the new type.49)

3 Otherwise, the new type is signed and the value cannot be
represented in it; either the result is implementation-defined or an
implementation-defined signal is raised.

Only p1 and p3 apply to signed integers. The behaviour is
implementation-defined.
 
N

Nick Keighley

Quite a high proportion of the traffic on clc is premised on the
assumption that there are insane implementors out there - don't spoil
the fun by bringing reality into the picture.

some of things you might think a reasonable person (for instance, me)
would think was insane have actually been implemented in the real
World.

- Some floating point formats are down right bizzare
- there really are 32-bit chars out there
- a char* may be larger than an int*
- 'A'-'Z' may not be contiguous
- a null pointer may not be all bits 0
- 0.0 may not be all bits zero
- a byte may not be an octet
- not all machines have hardware stacks
- an address may not be an integer
- an address may not fit in an int
- just looking at an invalid address may crash your program
- trap representations exist
 
S

santosh

Nick said:
some of things you might think a reasonable person (for instance, me)
would think was insane have actually been implemented in the real
World.

- Some floating point formats are down right bizzare
- there really are 32-bit chars out there
- a char* may be larger than an int*

Do you know a machine that implements this one?

<snip rest of list - please see previous post in thread>
 
B

Bartc

santosh said:
Do you know a machine that implements this one?

(You're not mistaking char larger than int?)

On word-addressable machines I'd imagine there could be a away of emulating
character access, with a int pointer plus a 'char within the int' index.

As for actual machines, well the pdp-10 had 36-bit words with 18-bit
addresses. But there were special bitfield-access instructions with a
complex pointer taking up 36 bits. Though I'm not familiar with C compilers
for it or whether int pointers were actually full or half-words.
 
S

santosh

Bartc said:
(You're not mistaking char larger than int?)

On word-addressable machines I'd imagine there could be a away of
emulating character access, with a int pointer plus a 'char within the
int' index.

If the bits for the index are within the int pointer, then a char * need
be no larger than an int *, though the address range for char * would
become shortened.
As for actual machines, well the pdp-10 had 36-bit words with 18-bit
addresses. But there were special bitfield-access instructions with a
complex pointer taking up 36 bits. Though I'm not familiar with C
compilers for it or whether int pointers were actually full or
half-words.

Hmm.
 
H

Harald van Dijk

@gmail.com wrote:
int rc;
char s[512];
rc = snprintf(s, sizeof s, "%p", (void *)s);
Or with a VLA:
char ptr[snprintf(NULL, 0, "%p", (void *)valid_ptr)+1];
No, it is not guaranteed that the text representation of a pointer
is less than 65534 bytes.
(ISO C99 TC3, 5.2.4.1 - Environmental limits)
[snip]
I don't think you understand. I did not talk about sizeof (pointer) (or
sizeof (int)). I talked about the text representation of the pointer, ie
what sprintf() would write to the buffer with the 'p' conversion
specifier.

But the only reason it could cause problems is because sizeof(ptr) (where
ptr happens to be an array) might exceed the environmental limit of 65535
bytes in an object, right? If you're talking about something else, then I
completely misunderstood your point, and I would appreciate a pointer in
the right direction. And I'll not respond to the rest of your message
while I'm unsure of what you mean. :)
 
R

Richard Bos

It's not so much that there are insane implementors, as that there are
(many!) imbecilic programmers. And that, alas, _is_ reality.
If the bits for the index are within the int pointer, then a char * need
be no larger than an int *, though the address range for char * would
become shortened.

That would not be allowed, however, since every single char in every
addressable int must itself be individually addressable.

Anyhow, ObFAQ: <http://c-faq.com/null/machexamp.html>.

Richard
 
V

vippstar

@gmail.com wrote:
int rc;
char s[512];
rc = snprintf(s, sizeof s, "%p", (void *)s);
Or with a VLA:
char ptr[snprintf(NULL, 0, "%p", (void *)valid_ptr)+1];
No, it is not guaranteed that the text representation of a pointer
is less than 65534 bytes.
(ISO C99 TC3, 5.2.4.1 - Environmental limits)
[snip]
I don't think you understand. I did not talk about sizeof (pointer) (or
sizeof (int)). I talked about the text representation of the pointer, ie
what sprintf() would write to the buffer with the 'p' conversion
specifier.

But the only reason it could cause problems is because sizeof(ptr) (where
ptr happens to be an array) might exceed the environmental limit of 65535
bytes in an object, right? If you're talking about something else, then I
completely misunderstood your point, and I would appreciate a pointer in
the right direction. And I'll not respond to the rest of your message
while I'm unsure of what you mean. :)
Where ptr is the same 'ptr' in Mr santosh' example? Yes, that is what
I'm talking about.
It's not going to happend anytime soon, but it's not hard to write an
implementation of printf() to make a point, %p could result in "The
pointer value is 0xHHHHHHH" (or a bigger message) for example.
 
H

Harald van Dijk

@gmail.com wrote:
int rc;
char s[512];
rc = snprintf(s, sizeof s, "%p", (void *)s);
Or with a VLA:
char ptr[snprintf(NULL, 0, "%p", (void *)valid_ptr)+1];
No, it is not guaranteed that the text representation of a
pointer is less than 65534 bytes.
(ISO C99 TC3, 5.2.4.1 - Environmental limits) [snip]
I don't think you understand. I did not talk about sizeof (pointer)
(or sizeof (int)). I talked about the text representation of the
pointer, ie what sprintf() would write to the buffer with the 'p'
conversion specifier.

But the only reason it could cause problems is because sizeof(ptr)
(where ptr happens to be an array) might exceed the environmental limit
of 65535 bytes in an object, right?

Where ptr is the same 'ptr' in Mr santosh' example? Yes, that is what
I'm talking about.

Okay, it was with that understanding that I replied to your post. My point
was that there are easier ways for implementations to make otherwise
correct programs exceed the environmental limits, so I'd worry about those
easier ways before this one. Those easier ways are so obviously insane
that no one is ever going to try it, so I don't worry about that. And
since making %p-formatted pointers excessively long is slightly more
complicated, I don't worry about that either.
It's not going to happend anytime soon, but it's not hard to write an
implementation of printf() to make a point, %p could result in "The
pointer value is 0xHHHHHHH" (or a bigger message) for example.

Oh, sure, and I wouldn't even have much of a problem with that. It's just
that I very strongly doubt that if the implementation does so, it prints a
string so large it itself cannot store it, even if you find a DS-9000.
 

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,792
Messages
2,569,639
Members
45,351
Latest member
RoxiePulli

Latest Threads

Top