2016-03-18 00:22:08 +03:00
/*
* Regression3
* Description :
* Helper radix_tree_iter_retry resets next_index to the current index .
* In following radix_tree_next_slot current chunk size becomes zero .
* This isn ' t checked and it tries to dereference null pointer in slot .
*
2016-03-18 00:22:11 +03:00
* Helper radix_tree_iter_next reset slot to NULL and next_index to index + 1 ,
* for tagger iteraction it also must reset cached tags in iterator to abort
* next radix_tree_next_slot and go to slow - path into radix_tree_next_chunk .
*
2016-03-18 00:22:08 +03:00
* Running :
* This test should run to completion immediately . The above bug would
* cause it to segfault .
*
* Upstream commit :
* Not yet
*/
# include <linux/kernel.h>
# include <linux/gfp.h>
# include <linux/slab.h>
# include <linux/radix-tree.h>
# include <stdlib.h>
# include <stdio.h>
# include "regression.h"
void regression3_test ( void )
{
RADIX_TREE ( root , GFP_KERNEL ) ;
2016-03-18 00:22:11 +03:00
void * ptr0 = ( void * ) 4ul ;
void * ptr = ( void * ) 8ul ;
2016-03-18 00:22:08 +03:00
struct radix_tree_iter iter ;
void * * slot ;
bool first ;
printf ( " running regression test 3 (should take milliseconds) \n " ) ;
2016-03-18 00:22:11 +03:00
radix_tree_insert ( & root , 0 , ptr0 ) ;
2016-03-18 00:22:08 +03:00
radix_tree_tag_set ( & root , 0 , 0 ) ;
first = true ;
radix_tree_for_each_tagged ( slot , & root , & iter , 0 , 0 ) {
2016-03-18 00:22:11 +03:00
printf ( " tagged %ld %p \n " , iter . index , * slot ) ;
2016-03-18 00:22:08 +03:00
if ( first ) {
radix_tree_insert ( & root , 1 , ptr ) ;
radix_tree_tag_set ( & root , 1 , 0 ) ;
first = false ;
}
if ( radix_tree_deref_retry ( * slot ) ) {
2016-03-18 00:22:11 +03:00
printf ( " retry at %ld \n " , iter . index ) ;
2016-03-18 00:22:08 +03:00
slot = radix_tree_iter_retry ( & iter ) ;
continue ;
}
}
radix_tree_delete ( & root , 1 ) ;
first = true ;
radix_tree_for_each_slot ( slot , & root , & iter , 0 ) {
2016-03-18 00:22:11 +03:00
printf ( " slot %ld %p \n " , iter . index , * slot ) ;
2016-03-18 00:22:08 +03:00
if ( first ) {
radix_tree_insert ( & root , 1 , ptr ) ;
first = false ;
}
if ( radix_tree_deref_retry ( * slot ) ) {
2016-03-18 00:22:11 +03:00
printk ( " retry at %ld \n " , iter . index ) ;
2016-03-18 00:22:08 +03:00
slot = radix_tree_iter_retry ( & iter ) ;
continue ;
}
}
radix_tree_delete ( & root , 1 ) ;
first = true ;
radix_tree_for_each_contig ( slot , & root , & iter , 0 ) {
2016-03-18 00:22:11 +03:00
printk ( " contig %ld %p \n " , iter . index , * slot ) ;
2016-03-18 00:22:08 +03:00
if ( first ) {
radix_tree_insert ( & root , 1 , ptr ) ;
first = false ;
}
if ( radix_tree_deref_retry ( * slot ) ) {
2016-03-18 00:22:11 +03:00
printk ( " retry at %ld \n " , iter . index ) ;
2016-03-18 00:22:08 +03:00
slot = radix_tree_iter_retry ( & iter ) ;
continue ;
}
}
2016-03-18 00:22:11 +03:00
radix_tree_for_each_slot ( slot , & root , & iter , 0 ) {
printf ( " slot %ld %p \n " , iter . index , * slot ) ;
if ( ! iter . index ) {
printf ( " next at %ld \n " , iter . index ) ;
slot = radix_tree_iter_next ( & iter ) ;
}
}
radix_tree_for_each_contig ( slot , & root , & iter , 0 ) {
printf ( " contig %ld %p \n " , iter . index , * slot ) ;
if ( ! iter . index ) {
printf ( " next at %ld \n " , iter . index ) ;
slot = radix_tree_iter_next ( & iter ) ;
}
}
radix_tree_tag_set ( & root , 0 , 0 ) ;
radix_tree_tag_set ( & root , 1 , 0 ) ;
radix_tree_for_each_tagged ( slot , & root , & iter , 0 , 0 ) {
printf ( " tagged %ld %p \n " , iter . index , * slot ) ;
if ( ! iter . index ) {
printf ( " next at %ld \n " , iter . index ) ;
slot = radix_tree_iter_next ( & iter ) ;
}
}
2016-03-18 00:22:08 +03:00
radix_tree_delete ( & root , 0 ) ;
radix_tree_delete ( & root , 1 ) ;
printf ( " regression test 3 passed \n " ) ;
}