NO

Author Topic: Safe Handles  (Read 5481 times)

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Safe Handles
« on: January 03, 2015, 01:30:19 AM »
Who write programs that create data structures and supply an handler for each one experience the problem to keep data safe from handlers misuse.
This small library helps on this issue.
Safe handles uses a table of corrispondence handle->memory pointer.
SafeHandles is thread safe. you can create handles concurrently in different threads while the library take care to avoid handles generation conflicts!  ;)
The size of the table is determined by the number of bits used for entries SAFEHANDLEENTRIESBITS. The you can change it depending on how many entries you want. Max allowed values is 16 bits. On 64 bits systems this limit can be as bigger as 32 bits. Larger the entries number less safe is the unique key that repeats more often.
A safe handle is an hashing like method to address data blocks, normally generated dinamically, avoiding memory conflicts and data corruption. Safehandles permits to define a type field that is encoded in the handle allowing distinction of data type just looking at the handle (think about GDI objects).
SafeHandles creates a memory table that stores key/data pairs. The size of the table is user defined. SafeHandles have 3 main parts:
Code: [Select]
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |           Unique key                  |  Type |    Table Ptr  |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The layout above is for a 32bits machine having up to 256 handles (8 bits), 16 types (4 bits) and 20bits of key. If MEMSAFE symbol is defined the handle will always have the MSBit set to address invalid memory. This prevents the use of handler to address memory, hiding any erroneous access to the real data.
The key changes for each new handle created, and wraps around when the max count for key bits is reached. This add safety for reused handles and should be safe enaugh for many applications. However the compiler will issue a message about the key enforcement, it is considered weak if the number of key bits is less than 8 times the table size.
Withstanding all these characteristics the access to the data is very fast and sanity check is strightforward.
To modify the default building of SafeHandles you can define preprocessor values:
  • SAFEHANDLEENTRIESBITS Set to the number of bits to be used for table indexing. Max value is 16 for 32bits machines and 32 for 64 bits machines.
  • SAFEHANDLETYPESBITS You can reserve bits to identify type of handle in programs where different objects are referenced. Default compile don't use types. Max value 8 for 32bits machines and 16 for 64 bits machines.
  • SAFEHANDLEMEMSAFE Define this variable to 1 to protect memory invalid access. Each generated handle will have the MSBit set. In this case using a safe handle to address memory will trigger a memory access exception. The cost is the loss of one bit on unique key.
  • SAFEHANDLEDYNMEM Define this variable to 1 to create table in dynamic memory. This is preferable when working with large tables

The test program check and stresses all functionalities.
The code is write to fit 32-64 bits machines, but the 64bits version has not been tested. Glad if someone would do this job...

EDIT: The final release is available on CodeProject.
« Last Edit: January 20, 2015, 06:40:21 PM by frankie »
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

Offline jj2007

  • Member
  • *
  • Posts: 536
Re: Safe Handles
« Reply #1 on: January 03, 2015, 10:42:00 AM »
Nice work, frankie, but excuse an ignorant question: should handle "misuse" ever happen in an app where the coder still knows what he is doing? In the last twenty years or so, whenever I had heap corruption or similar "events", I considered this a bug worth to be chasen the whole night if necessary... and that chasing won't become easier if there is some engine in the background trying to "save" the app despite of the bug.

But you certainly know what you are doing. Maybe you have a crispy example where handle misuse can happen despite of proper cleanup procedures etc?

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: Safe Handles
« Reply #2 on: January 03, 2015, 02:41:49 PM »
Nice work, frankie, but excuse an ignorant question: should handle "misuse" ever happen in an app where the coder still knows what he is doing?
If you craft a library that gives back handles when an instance is created you don't know what the user (or misuser) will do with that handles...  ;)
And this will save reputation of your library too...  ;)
Moreover it helps against reuse of released handle (simple memory pointer will give a memory access exception when used on freed memory) using safehandles you will get an error when requiring data pointer from handle, helps when you wrongly use a pointer instead of another, etc...
It is helpfull when dealing with critical projects where data mishandling can create serious system problems, for simple programs where pointer confusion is not a big deal this code is unneneccessary.
I forget to mention that the genration is thread safe.
« Last Edit: January 03, 2015, 03:19:24 PM by frankie »
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

Offline jj2007

  • Member
  • *
  • Posts: 536
Re: Safe Handles
« Reply #3 on: January 04, 2015, 02:58:56 AM »
for simple programs where pointer confusion is not a big deal this code is unneneccessary.
Thanks for the explanation, Frankie. So the bigger the project, the more confused the pointers? That would explain some, ehm, critical aspects of Adobe's products ;-)

You might add a verbose mode. For example, if the user tries to access a freed handle and the project is in debug mode, a warning could be shown.