From:             test dot 007 at seznam dot cz
Operating system: any
PHP version:      5CVS-2004-08-31 (dev)
PHP Bug Type:     Reproducible crash
Bug description:  allocate_new_resource() dangling pointer

Description:
------------
There's a dangling pointer in TSRM.c: allocate_new_resource(),  the last
command.
After 
tsrm_mutex_unlock(tsmm_mutex);
the (*thread_resources_ptr) is invalid if you're really unlucky.

Fix:
diff ..\php-4.3.8.orig\TSRM\TSRM.c TSRM\TSRM.c
258a259
>     tsrm_tls_entry *new_resource;
261a263
>     new_resource = (*thread_resources_ptr);
291c293
<               tsrm_new_thread_end_handler(thread_id,
&((*thread_resources_ptr)->storage));
---
>               tsrm_new_thread_end_handler(thread_id, &((new_resource)->storage));

Long description:
I believe there's a bug even in latest PHP 5, which crashes more probably
in debug build, see TSRM/tsrm.c:
ts_resource_ex() calls while owning a mutex:
allocate_new_resource(&thread_resources->next, thread_id);
That should add a new tsrm_tls_entry* thread_resources to the end of the
linked list.
allocate_new_resource(tsrm_tls_entry **thread_resources_ptr, THREAD_T
thread_id) adds a new linked entry (i.e. sets the list tail's next)
(*thread_resources_ptr) = (tsrm_tls_entry *)
malloc(sizeof(tsrm_tls_entry));
unlock the mutex;
tsrm_new_thread_end_handler(thread_id,
&((*thread_resources_ptr)->storage)); /* 2nd arg equals to
(*thread_resources_ptr) */
If another thread, by accident exactly the thread which has been the last
one in the linked list before the allocate_new_resource() called malloc(),
and whose "next" entry was set there, calls ts_free_thread(), it free()s
the thread_resources of ts_resource_ex() -- 
in debug build, the (thread_resources->next) vulgo (*thread_resources_ptr)
is set to 0xfeeefeee, and the call tsrm_new_thread_end_handler(0xfeeefeee)
crashes; 
in release build, the memory can be used by another malloc() or
decommited, but probably, in the very short period this dangling pointer
is used, it's not overwritten, thus the code executes almost always
without crash. 

The solution is to store (*thread_resources_ptr) on stack anytimes between
malloc() and unlock.

Reproduce code:
---------------
You need to run multiple threads and call ts_free_thread() from them
regularly (is it correct?). 
You need the thread hash table to be too small so that hash collisions
occur. To crash you need the tail of a linked list to call
ts_free_thread() at the same time a new tail is added.


-- 
Edit bug report at http://bugs.php.net/?id=29915&edit=1
-- 
Try a CVS snapshot (php4):   http://bugs.php.net/fix.php?id=29915&r=trysnapshot4
Try a CVS snapshot (php5.0): http://bugs.php.net/fix.php?id=29915&r=trysnapshot50
Try a CVS snapshot (php5.1): http://bugs.php.net/fix.php?id=29915&r=trysnapshot51
Fixed in CVS:                http://bugs.php.net/fix.php?id=29915&r=fixedcvs
Fixed in release:            http://bugs.php.net/fix.php?id=29915&r=alreadyfixed
Need backtrace:              http://bugs.php.net/fix.php?id=29915&r=needtrace
Need Reproduce Script:       http://bugs.php.net/fix.php?id=29915&r=needscript
Try newer version:           http://bugs.php.net/fix.php?id=29915&r=oldversion
Not developer issue:         http://bugs.php.net/fix.php?id=29915&r=support
Expected behavior:           http://bugs.php.net/fix.php?id=29915&r=notwrong
Not enough info:             http://bugs.php.net/fix.php?id=29915&r=notenoughinfo
Submitted twice:             http://bugs.php.net/fix.php?id=29915&r=submittedtwice
register_globals:            http://bugs.php.net/fix.php?id=29915&r=globals
PHP 3 support discontinued:  http://bugs.php.net/fix.php?id=29915&r=php3
Daylight Savings:            http://bugs.php.net/fix.php?id=29915&r=dst
IIS Stability:               http://bugs.php.net/fix.php?id=29915&r=isapi
Install GNU Sed:             http://bugs.php.net/fix.php?id=29915&r=gnused
Floating point limitations:  http://bugs.php.net/fix.php?id=29915&r=float

Reply via email to