views:

551

answers:

7

I like to have my code warning free for VS.NET and GCC, and I like to have my code 64 bit ready.

Today I wrote a little module that deals with in memory buffers and provides access to the data via a file-style interface (e.g. you can read bytes, write bytes, seek around ect.).

As the data-type for current read position and size I used size_t since that seemes to be the most natural choice. I get around the warnings and it ought to work in 64 bit as well.

Just in case: My structure looks like this:

typedef struct
{
  unsigned char * m_Data;
  size_t          m_CurrentReadPosition;
  size_t          m_DataSize;
} MyMemoryFile;

The sign-ness (is this the correct word btw?) of size_t seems not to be defined in practice. A Google code-search proved that.

Now I'm in a dilemma: I want to check additions with size_t for overflows because I have to deal with user supplied data and third party libraries will use my code. However, for the overflow check I have to know the sign-ness. It makes a huge difference in the implementation.

So - how the heck should I write such a code in a platform and compiler independent way?

Can I check the sign-ness of size_t at run or compile-time? That would solve my problem. Or maybe size_t wasn't the best idea at the first place?

Any ideas?

EDIT: I'm looking for a solution for the C-language!

+3  A: 

size_t should be unsigned.

its typically defined as unsigned long.

I've never seen it be defined otherwise. ssize_t is its signed counterpart.

EDIT: GCC defines it as signed in some circumstances. compiling in ASNI C mode or std-99 should force it to be unsigned.

Nicholas Mancuso
GCC defines size_t as signed :(
Nils Pipenbrinck
Isn't unsigned long 32 bits in 64 bit windows? Not a good assumption for size_t.
ejgottl
g++ 4.2.3 defines it as unsigned.
ejgottl
A: 

Use safeint. It is a class designed by Michael Howard and released as open source from Microsoft. It is designed to make working with integers where overflow is identified as a risk. All overflows are converted to exceptions and handled. The class is designed to make correct usage easy.

For example :

char CouldBlowUp(char a, char b, char c)
{
   SafeInt<char> sa(a), sb(b), sc(c);

   try
   {
     return (sa * sb + sc).Value();
   }
   catch(SafeIntException err)
   {
      ComplainLoudly(err.m_code);
   }

   return 0;
}

Also safeint is used a lot internally at Microsoft in products like Office.

Ref: link text

1800 INFORMATION
I can't use SaveInt. I'm C-only, and afaik saveint does not solve the sign-ness problem as well because it assumes the defaults from msvc.
Nils Pipenbrinck
Oh right the question was initially marked as C++. See my other answer for a C language library.
1800 INFORMATION
Yes - I know. Sorry about that. I edited the question to make sure I don't mislead anyone else.
Nils Pipenbrinck
A: 

I am not sure if I don't understand exactly the question, but maybe you can do something like:

temp = value_to_be_added_to;

value_to_be_added_to += value_to_add;

if (temp > value_to_be_added_to) { overflow... }

Since it will wrap back to lower values you can check easily if it overflowed.

Francisco Soto
What if value_to_add is negative?
Dour High Arch
Check the contrary.
Francisco Soto
+2  A: 

For C language, use IntSafe. Also released by Microsoft (not to be confused with the C++ library SafeInt). IntSafe is a set of C language function calls that can perform math and do conversions safely.

1800 INFORMATION
+3  A: 

size_t is an unsigned integral type, according to the C++ C standards. Any implementation that has size_t signed is seriously nonconforming, and probably has other portability problems as well. It is guaranteed to wrap around when overflowing, meaning that you can write tests like "if (a + b < a)" to find overflow.

size_t is an excellent type for anything involving memory. You're doing it right.

David Thornley
+6  A: 

Regarding the whether size_t is signed or unsigned and GCC (from an old GCC manual - I'm not sure if it's still there):

There is a potential problem with the size_t type and versions of GCC prior to release 2.4. ANSI C requires that size_t always be an unsigned type. For compatibility with existing systems' header files, GCC defines size_t in stddef.h to be whatever type the system's sys/types.h defines it to be. Most Unix systems that define size_t in sys/types.h, define it to be a signed type. Some code in the library depends on size_t being an unsigned type, and will not work correctly if it is signed.

The GNU C library code which expects size_t to be unsigned is correct. The definition of size_t as a signed type is incorrect. We plan that in version 2.4, GCC will always define size_t as an unsigned type, and the 'fixincludes' script will massage the system's sys/types.h so as not to conflict with this.

In the meantime, we work around this problem by telling GCC explicitly to use an unsigned type for size_t when compiling the GNU C library. 'configure' will automatically detect what type GCC uses for size_t arrange to override it if necessary.

If you want a signed version of size_t use ptrdiff_t or on some systems there is a typedef for ssize_t.

Michael Burr
wow! thanks a lot for digging for the history of the issue.
Nils Pipenbrinck
Had to do it for my own curiosity - I found it hard to believe that GCC would disregard a pretty basic part of the standard without a decent explanation.
Michael Burr
A: 

There seems to be a lot of interest in integer overflow recently:

http://stackoverflow.com/questions/199333/best-way-to-detect-integer-overflow-in-cc

Has there been some recent exploit I haven't heard about?

Michael Burr
Yep. there are a lot of exploits. Just do a google on CERT, integer and overflow. You'll be surprised how common that problem is.
Nils Pipenbrinck