Search code examples
cvoid-pointersmisraqualifiers

How to write a memcpy function full MISRA:2012 compatible?


I wrote this memcpy function, but I still need to disable rules 11.5 and 11.8. Is there a solution to be full MISRA:2012 compatible?

#pragma cstat_suppress="MISRAC2012-Rule-21.6" // Uses of stdio.h were found.
#include <stdio.h>

#include <stdint.h>
#include <string.h>
#include <stdlib.h>

extern int main(void);

static int_least8_t _memcpy(void *dst, const void *src, const size_t length)
{
    #pragma cstat_disable="MISRAC2012-Rule-11.5" // A conversion from a pointer to void into a pointer to object was found.
    int_least8_t* destination = (int_least8_t*)dst;
    #pragma cstat_disable="MISRAC2012-Rule-11.8" // A cast that removes a const or volatile qualification was found.
    const int_least8_t* source = (int_least8_t*)src;
    #pragma cstat_restore="MISRAC2012-Rule-11.5","MISRAC2012-Rule-11.8"

    for (size_t i = 0; i < (length / sizeof(int_least8_t)); i++)
    {
        destination[i] = source[i];
    }
    return 0;
}

int main(void)
{
    int32_t src[32];
    int32_t dst[32];

    (void)memset(src, 0xff, sizeof(src));

    (void)_memcpy(dst, src, 128);

    for (size_t i = 0; i < (sizeof(src) / sizeof(src[0])); i++)
    {
        (void)printf("%d <=> %d\n", src[i], dst[i]);
    }

    return 0;
}

I am using IAR as a compiler and C-STAT for static analysis.


Solution

  • There is no way you can write memcpy with the standard format and be fully MISRA compliant. As you seem to have noticed, MISRA doesn't allow restrict. But there's also the rule 11.5.

    Rule 11.5 regarding casts from pointer-to-void to pointer-to-type is just too cumbersome to follow in practice. It is an Advisory rule so I would just skip it. You don't need to raise a deviation.

    Rule 11.8 regarding casting away qualifiers is a sound one however (and Required). There is no reason why you should do this in this case. There is a bug in your code which was prevented by MISRA. Change the code to

    const int_least8_t* source = (const int_least8_t*) src;
    

    Additional notes:

    • You need not provide a function declaration to main().
    • stdio.h is not allowed by MISRA-C.
    • Avoid declaring identifiers starting with an underscore, see C11 7.1.3.
    • There's no apparent benefit of using int_least8_t here. In addition, signed types are problematic. I would use uint8_t instead.