php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #80965 A use after free bug in ext/spl/spl_dllist.c
Submitted: 2021-04-18 07:03 UTC Modified: 2021-04-19 12:46 UTC
From: lylgood at foxmail dot com Assigned:
Status: Not a bug Package: *Extensibility Functions
PHP Version: master-Git-2021-04-18 (Git) OS: All
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: lylgood at foxmail dot com
New email:
PHP Version: OS:

 

 [2021-04-18 07:03 UTC] lylgood at foxmail dot com
Description:
------------
File: ext/spl/spl_dllist.c
Bug Function: PHP_METHOD(SplDoublyLinkedList, offsetUnset)

In this function, element is obtained via spl_ptr_llist_offset() at line 834.
At line 863, the ref of element is decreased by one via SPL_LLIST_DELREF(element), if the refcount of element is  0 now, the element will be freed. 

But the freed element is still used at line 869 by SPL_LLIST_DELREF(element) which   is a macro of "if (!-- ((element)->data).u2.extra) { _efree((element)); }". It is a use after free.

If the freed memory of element is allocated by other objects before line 869,
then it is possible to fake structures to modify the refcount of element and cause an additional double free.

Test script:
---------------
      
834:  element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO);	
      ...	
      if (intern->traverse_pointer == element) {
863:  SPL_LLIST_DELREF(element);   // element First freed here!
      intern->traverse_pointer = NULL;
      }
      zval_ptr_dtor(&element->data);
      ZVAL_UNDEF(&element->data);

869:  SPL_LLIST_DELREF(element)  // Freed element is used and could be freed again!


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-04-19 12:43 UTC] nikic@php.net
This would only cause a use-after-free if some code setting traverse_pointer did not increment the refcount. Otherwise this will only decrement the refcount, without freeing.
 [2021-04-19 12:46 UTC] nikic@php.net
-Status: Open +Status: Not a bug
 [2021-04-19 12:46 UTC] nikic@php.net
.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 25 23:01:29 2024 UTC