Go Back   Rhinocerus > Newsgroup > Newsgroup comp.language.c++

Reply
 
Thread Tools Display Modes
  #1 (permalink)  
Old 04-28-2012, 03:11 PM
Nephi Immortal
Guest
 
Posts: n/a
Default Possible buffer overruns?

When you place a string between two quote marks in the function’s
parameter, how many characters should be limited? The character
length should be 256.

For example

void Test( char* text ) { …. }

Test( “0123456789” );

If character length is to be 512, 1024, or 4096, string is too big to
fit into the stack.

If anyone plants virus program into memory, it is possible to cause
that buffer overruns unless null terminator is overwritten with new
character value.

The condition is shown *ptr != ‘\0’ is unsafe. More safe condition
should be added. If buffer goes past overwritten null terminator,
buffer overruns can be avoided with limited character garbages.

char A[ 256 ] =
"0123456789";


int main()
{
const int BUFFER_SIZE = 256;

char B [ 256 ];

int index = 0;

do
{
B[ index ] = A[ index ];
++index;
}
while( index < BUFFER_SIZE - 1 && A[ index ] != '\0' ); // safe
// while(A[ index ] != '\0' ); // unsafe


B[ index ] = '\0';

return 0;
}
Reply With Quote
Alt Today
Advertising
 
and become member of Rhinocerus
Standard Sponsored Links

  #2 (permalink)  
Old 04-28-2012, 03:35 PM
Paavo Helde
Guest
 
Posts: n/a
Default Re: Possible buffer overruns?

Nephi Immortal <immortalnephi@gmail.com> wrote in news:88995416-31ea-
441d-9744-81e43b0afa15@n19g2000yqk.googlegroups.com:

> When you place a string between two quote marks in the function’s
> parameter, how many characters should be limited? The character
> length should be 256.
>
> For example
>
> void Test( char* text ) { …. }
>
> Test( “0123456789” );
>
> If character length is to be 512, 1024, or 4096, string is too big to
> fit into the stack.
>
> If anyone plants virus program into memory, it is possible to cause
> that buffer overruns unless null terminator is overwritten with new
> character value.
>
> The condition is shown *ptr != ‘\0’ is unsafe. More safe condition
> should be added. If buffer goes past overwritten null terminator,
> buffer overruns can be avoided with limited character garbages.
>
> char A[ 256 ] "0123456789";
>
>
> int main()
> {
> const int BUFFER_SIZE = 256;
>
> char B [ 256 ];
>
> int index = 0;
>
> do
> {
> B[ index ] = A[ index ];
> ++index;
> }
> while( index < BUFFER_SIZE - 1 && A[ index ] != '\0' ); // safe
> // while(A[ index ] != '\0' ); // unsafe
>
>
> B[ index ] = '\0';
>
> return 0;
> }


You are solving an unexisting problem (at least in comp.lang.c++).

#include <string>

std::string a("0123456789");

int main() {
std::string b = a; // safe
}

Extra bonus: you can have very large strings, no stack overflow with a
std::string.

nrhth
Paavo




Reply With Quote
  #3 (permalink)  
Old 04-28-2012, 07:06 PM
Nephi Immortal
Guest
 
Posts: n/a
Default Re: Possible buffer overruns?

On Apr 28, 10:35*am, Paavo Helde <myfirstn...@osa.pri.ee> wrote:
> Nephi Immortal <immortalne...@gmail.com> wrote in news:88995416-31ea-
> 441d-9744-81e43b0af...@n19g2000yqk.googlegroups.com:
>
>
>
>
>
> > When you place a string between two quote marks in the function’s
> > parameter, how many characters should be limited? *The character
> > length should be 256.

>
> > For example

>
> > void Test( char* text ) { …. }

>
> > Test( “0123456789” );

>
> > If character length is to be 512, 1024, or 4096, string is too big to
> > fit into the stack.

>
> > If anyone plants virus program into memory, it is possible to cause
> > that buffer overruns unless null terminator is overwritten with new
> > character value.

>
> > The condition is shown *ptr != ‘\0’ is unsafe. *More safe condition
> > should be added. *If buffer goes past overwritten null terminator,
> > buffer overruns can be avoided with limited character garbages.

>
> > char A[ 256 ] * * *"0123456789";

>
> > int main()
> > {
> > * * *const int BUFFER_SIZE = 256;

>
> > * * *char B [ 256 ];

>
> > * * *int index = 0;

>
> > * * *do
> > * * *{
> > * * * * * B[ index ] = A[ index ];
> > * * * * * ++index;
> > * * *}
> > * * *while( index < BUFFER_SIZE - 1 && A[ index ] != '\0' ); //safe
> > // * * while(A[ index ] != '\0' ); // unsafe

>
> > * * *B[ index ] = '\0';

>
> > * * *return 0;
> > }

>
> You are solving an unexisting problem (at least in comp.lang.c++).
>
> #include <string>
>
> std::string a("0123456789");
>
> int main() {
> * * * * std::string b = a; // safe
>
> }
>
> Extra bonus: you can have very large strings, no stack overflow with a
> std::string.


std::string's data members (including base pointer and size) are
allocated into stack, but string allocates any number of bytes into
heap. String has no big deal, but I talk about traditional C string.
You need to take care to limit the number of characters because it
does not know the length until reaching null terminator.

std::string( "0123456789", 10 ) is both C string and C++ string.
"0123456789" including null terminator in string constructor is C
string and it is always pushed into stack before main function begins
and pop out after main function ends. string constructor ignores null
terminator unless length is included in the function parameter. It
allocates 10 bytes into heap before each character is copied from
stack to heap.

If you show std::string( "0123456789" ) instead of
std::string( "0123456789", 10 ), how can string constructor copy more
than ten characters unless null terminator is overwritten with any
character value in memory by virus program and until finding null
terminator before garbage characters are copied?



Reply With Quote
  #4 (permalink)  
Old 04-28-2012, 07:31 PM
Paavo Helde
Guest
 
Posts: n/a
Default Re: Possible buffer overruns?

Nephi Immortal <immortalnephi@gmail.com> wrote in news:2ce08a82-a893-
4910-869b-a9697d829c82@9g2000yqp.googlegroups.com:
>
> std::string( "0123456789", 10 ) is both C string and C++ string.
> "0123456789" including null terminator in string constructor is C
> string and it is always pushed into stack


No. The string literal is placed in a data segment in the compiled
executable and is not copied anywhere from there without the program's
consent.

> before main function begins
> and pop out after main function ends.


You are talking nonsense.

> string constructor ignores null
> terminator unless length is included in the function parameter. It
> allocates 10 bytes into heap before each character is copied from
> stack to heap.
>
> If you show std::string( "0123456789" ) instead of
> std::string( "0123456789", 10 ), how can string constructor copy more
> than ten characters unless null terminator is overwritten with any
> character value in memory by virus program and until finding null
> terminator before garbage characters are copied?


The evil virus cannot overwrite the null terminator as in a typical
implementation the string literal is placed in a read-only memory
segment.

Also, you have the virus functionality backwards - the buffer overrun
exploit first attempts to snigger in a too large string which does not
fit into buffer, and gain access via that. In your scenario virus has
already gained access and then trying to enlarge the string by deleting a
zero terminator - this is backwards.

cheers
Paavo




Reply With Quote
  #5 (permalink)  
Old 04-28-2012, 08:18 PM
Nephi Immortal
Guest
 
Posts: n/a
Default Re: Possible buffer overruns?

On Apr 28, 2:31*pm, Paavo Helde <myfirstn...@osa.pri.ee> wrote:
> Nephi Immortal <immortalne...@gmail.com> wrote in news:2ce08a82-a893-
> 4910-869b-a9697d829...@9g2000yqp.googlegroups.com:
>
>
>
> > std::string( "0123456789", 10 ) is both C string and C++ string.
> > "0123456789" including null terminator in string constructor is C
> > string and it is always pushed into stack

>
> No. The string literal is placed in a data segment in the compiled
> executable and is not copied anywhere from there without the program's
> consent.
>
> > before main function begins
> > and pop out after main function ends.

>
> You are talking nonsense.
>
> > string constructor ignores null
> > terminator unless length is included in the function parameter. *It
> > allocates 10 bytes into heap before each character is copied from
> > stack to heap.

>
> > If you show std::string( "0123456789" ) instead of
> > std::string( "0123456789", 10 ), how can string constructor copy more
> > than ten characters unless null terminator is overwritten with any
> > character value in memory by virus program and until finding null
> > terminator before garbage characters are copied?

>
> The evil virus cannot overwrite the null terminator as in a typical
> implementation the string literal is placed in a read-only memory
> segment.
>
> Also, you have the virus functionality backwards - the buffer overrun
> exploit first attempts to snigger in a too large string which does not
> fit into buffer, and gain access via that. In your scenario virus has
> already gained access and then trying to enlarge the string by deleting a
> zero terminator - this is backwards.


if the code shows below,

int main()
{
const char* A = "0123456789"; // store in stack
const char B[ 10 + 1 ] = "0123456789"; // store in stack
static const char C[] = "0123456789"; // store in data segment

return 0;
}

then do both A and B store 11 characters into stack and C into data
segment?

If you say data segment, then it should look like this below

void foo( "0123456789" ); // store string in data segment

// global scope
const char X[] = "0123456789"; // store string in stack?

struct bar
{
static const char N[];
}

const char bar::N[] = "0123456789"; // store string in data segment

You mentioned that data segment is read only. Can separate data
segment be read/write unless string is non-constant?
Reply With Quote
  #6 (permalink)  
Old 04-28-2012, 08:55 PM
Paavo Helde
Guest
 
Posts: n/a
Default Re: Possible buffer overruns?

Nephi Immortal <immortalnephi@gmail.com> wrote in
news:44b62e39-e7bd-4b25-b7bf-b0389f365ba6@2g2000yqk.googlegroups.com:
> if the code shows below,
>
> int main()
> {
> const char* A = "0123456789"; // store in stack
> const char B[ 10 + 1 ] = "0123456789"; // store in stack
> static const char C[] = "0123456789"; // store in data segment
>
> return 0;
> }
>
> then do both A and B store 11 characters into stack and C into data
> segment?


Why don't you check by yourself? Here is an example program:

#include <iostream>

int main()
{
int stack_top;

const char* A = "0123456789"; // store in stack
const char B[ 10 + 1 ] = "0123456789"; // store in stack

int before_C;
static const char C[] = "0123456789"; // store in data segment
int after_C;

std::cout << "A takes "
<< ( (char*) &stack_top - (char*) &A)
<< " bytes in the stack\n";
std::cout << "B takes "
<< ( (char*) &A - (char*) &B)
<< " bytes in the stack\n";
std::cout << "C takes "
<< ( (char*) &before_C - (char*) &after_C - sizeof(after_C))
<< " bytes in the stack\n";

return 0;
}

In MSVC 32-bit Debug mode (no smart optimizations done by the compiler!)
this prints out:

A takes 4 bytes in the stack
B takes 12 bytes in the stack
C takes 0 bytes in the stack

A is a 4-byte pointer on the stack, the string literal is by itself in
some (read-only) data segment.

B is indeed 11 bytes on stack, 1 extra byte for alignment padding.

C seems to be indeed in a data segment.


>
> If you say data segment, then it should look like this below
>
> void foo( "0123456789" ); // store string in data segment


String literal is in a read-only data segment. A pointer to it is passed
to foo().

>
> // global scope
> const char X[] = "0123456789"; // store string in stack?


If it is in global scope, then there is no stack involved. Stack is
related to the actual execution thread; in a multi-threaded program each
thread has its own stack memory, but global variables are visible in all
threads. This already shows they are not on stack.

The string literal itself is placed in a read-only data segment. A copy
may be made for X and placed in a read-write or read-only data segment. I
guess an optimizer is allowed to coalesce these things into one, but not
100% sure.

>
> struct bar
> {
> static const char N[];
> }
>
> const char bar::N[] = "0123456789"; // store string in data segment


This is the same as X I think.

>
> You mentioned that data segment is read only. Can separate data
> segment be read/write unless string is non-constant?


Sure, there are read-write data segments as well. Non-const global
variables go there for sure.

hth
Paavo

Reply With Quote
  #7 (permalink)  
Old 04-29-2012, 05:44 AM
Juha Nieminen
Guest
 
Posts: n/a
Default Re: Possible buffer overruns?

Nephi Immortal <immortalnephi@gmail.com> wrote:
> When you place a string between two quote marks in the function???s
> parameter, how many characters should be limited? The character
> length should be 256.
>
> For example
>
> void Test( char* text ) { ???. }
>
> Test( ???0123456789??? );
>
> If character length is to be 512, 1024, or 4096, string is too big to
> fit into the stack.


What a load of BS. When you call 'Test()' above, the only thing that
gets put onto the stack is one pointer.
Reply With Quote
 
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off




All times are GMT. The time now is 06:26 AM.


Copyright ©2009

LinkBacks Enabled by vBSEO 3.3.0 RC2 © 2009, Crawlability, Inc.