none
ArrayList in kernel mode? RRS feed

  • Question

  • Since some days ago, i comes trying implement a functional example of arraylist in C (windows kernel), saw several examples of arraylist implementation in C (usermode), so i decided pass this specific example to kernel code (already that seems the more easy example between others that i saw), now i have this code below that still not works and comes a bsod. What's wrong?

    I hoope that someone give me a solution that can solve this for always :-)

    Thank you.

    #include <ntddk.h>
    #include <WinDef.h>
    ///////////////////////////////////// START ARRAYLIST /////////////////////////////////////////
    
    typedef char* value_type;
    
    typedef struct arraylist{
        size_t size;
        value_type* data;
    }arraylist;
    
    ///////////////////////////////////////////////////
    
    void free(const void*mem)
    {
        if (mem)
        {
            arraylist *base = (arraylist*)(((size_t)mem) - sizeof(arraylist));
            ExFreePool(base);
        }
    }
    
    void* malloc(size_t size)
    {
        if (sizeof(arraylist) + size < size)
            return NULL; 
    
        void *base = ExAllocatePoolWithTag(NonPagedPool, sizeof(arraylist) + size, 'MyTG' );
        if (!base)
            return base;
    
        arraylist *pHeader = (arraylist*)base;
        pHeader->size = size;
    
        return (void*)(((size_t)base) + sizeof(arraylist));
    }
    
    void* realloc(void*oldmem, size_t newsize)
    {
        arraylist *pHeader = oldmem ? (arraylist*)(((size_t)oldmem) - sizeof(arraylist)) : NULL;
    
        size_t oldsize = pHeader ? pHeader->size : 0;
        if (oldsize >= newsize)
            return oldmem;
    
        void *newmem = malloc(newsize);
        if (newmem)
        {
            memcpy(newmem, oldmem, oldsize);
            free(oldmem);
        }
        return newmem;
    }
    
    ///////////////////////////////////////////////////
    
    void arraylist_initial(struct arraylist *list) {
    
        list->size = 0;
        list->data = NULL;
    }
    
    int arraylist_get_size(const struct arraylist list) {
    
        return list.size;
    }
    
    void arraylist_set_data_collection(struct arraylist *list, value_type* data) {
    
        list->data = data;
    }
    
    void arraylist_add(struct arraylist *list, value_type value) {
    
        int size = arraylist_get_size(*list);
        value_type *new_data;
    
        new_data = realloc(list->data, (size + 1) * sizeof new_data[0]);
    
        if (new_data)
        {
            new_data[size] = value;
            arraylist_set_data_collection(list, new_data);
            ++list->size;
        }
    }
    
    value_type arraylist_get(const struct arraylist list, int index) {
    
        if (index < arraylist_get_size(list)) {
            return list.data[index];
        }
        else {
            return NULL;
        }
    }
    
    void arraylist_clear(struct arraylist *list) {
    
        list->size = 0;
        free(list->data);
        list->data = NULL;
    }
    
    void arraylist_deallocate(struct arraylist *list) {
    
        if (list->data != NULL)
            free(list->data);
        free(list);
    }
    
    int arraylist_indexof(const struct arraylist list, value_type value) {
    
        int index = 0;
        for (; index != arraylist_get_size(list); ++index) {
            if (strcmp(list.data[index], value) == 0) {
                return index;
            }
        }
    
        return -1;
    }
    
    struct arraylist list;
    
    ///////////////////////////////// END ARRAYLIST ///////////////////////////////////
    
    void listUnload(IN PDRIVER_OBJECT DriverObject)
    {
        DbgPrint("Goodbye from list!\n");
    }
    
    NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath)
    {
    
        arraylist_initial(&list);
    
        arraylist_add(&list, "1");
        arraylist_add(&list, "2");
        arraylist_add(&list, "3");
        arraylist_add(&list, "4");
        arraylist_add(&list, "5");
        arraylist_add(&list, "6");
        arraylist_add(&list, "7");
    
    
        int index = 0;
        for (; index != 7; ++index) {
            DbgPrint("CHECK: %s\n", arraylist_get(list, index));
    
        }
    
        int my_value = arraylist_indexof(list, "4");
    
        DbgPrint("size: %d index: %d\n", arraylist_get_size(list), my_value);
    
        arraylist_clear(&list);
        arraylist_deallocate(&list);
    
        DriverObject->DriverUnload = listUnload;
    
        DbgPrint("Hello from list!\n");
    
        return STATUS_SUCCESS;
    }


    • Edited by FLASHCODR Wednesday, April 18, 2018 3:41 AM
    Wednesday, April 18, 2018 3:41 AM

All replies

  • Can you get the dump, then use Windbg to run !analyze -v on the dump?  With the symbols set up correctly, that in most cases isolates the failure very quickly.


    Don Burn Windows Driver Consulting Website: http://www.windrvr.com

    Wednesday, April 18, 2018 1:49 PM
  • If you had done the sensible thing, and tested this mess in user-mode where debugging is easy, you would have located the problem right away.  That's exactly what I did.  The thing that causes the crash is this:

        arraylist_deallocate(&list);

    because "list" is not a pointer.  It was never allocated.  "list" is a global.  You can't free a global.

    However, I don't think you have thought this whole concept through.  You are storing string pointers here. That means this can only work with string constants.  You might think you could write this:

        char testing[40];
        strcpy( sss, "hey" );
        arraylist_add(&list, sss);
        strcpy( sss, "you" );
        arraylist_add(&list, sss);
        strcpy( sss, "what" );
        arraylist_add(&list, sss);
        strcpy( sss, "are" );
        arraylist_add(&list, sss);
        strcpy( sss, "you" );
        arraylist_add(&list, sss);
        strcpy( sss, "doing?" );
        arraylist_add(&list, sss);

    but you would be wrong.  You would end up with 6 identical entries containing "doing?".  Even worse, once this function returned, the entries would all point into empty space, because the stack is gone.

    It's very difficult to write useful generic containers.  I suggest you not try.


    Tim Roberts, Driver MVP Providenza & Boekelheide, Inc.

    Saturday, April 21, 2018 12:03 AM