zephyr/lib/cmsis_rtos_v2/timer.c
Carlos Stuart d47178bc95 lib: cmsis_rtos_v2: Default name if name is NULL
Fixed an issue whereby if an attribute structure was passed into a CMSIS
RTOS v2 'new' function with an invalid address i.e. NULL assigned to the
name (char*) member the memcpy at the end of each new function
would cause a segmentation fault i.e. read from an invalid
address.

This has been fixed by checking if the name is NULL and using the
default name from the init struct if it is. This is the same name
that would be used if not passing in the optional attr function
argument.

Changed the memcpy to strncpy to ensure that the copy does not read
beyond the end of the source string and changed the length from 16 to 15
(by means of a `sizeof(...)-1`) of the destination buffer to ensure that
it will always be nul-terminated.

Signed-off-by: Carlos Stuart <carlosstuart1970@gmail.com>
2019-02-06 10:20:17 -05:00

177 lines
3.3 KiB
C

/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <kernel_structs.h>
#include "wrapper.h"
#define ACTIVE 1
#define NOT_ACTIVE 0
static void zephyr_timer_wrapper(struct k_timer *timer);
K_MEM_SLAB_DEFINE(cv2_timer_slab, sizeof(struct cv2_timer),
CONFIG_CMSIS_V2_TIMER_MAX_COUNT, 4);
static const osTimerAttr_t init_timer_attrs = {
.name = "ZephyrTimer",
.attr_bits = 0,
.cb_mem = NULL,
.cb_size = 0,
};
static void zephyr_timer_wrapper(struct k_timer *timer)
{
struct cv2_timer *cm_timer;
cm_timer = CONTAINER_OF(timer, struct cv2_timer, z_timer);
(cm_timer->callback_function)(cm_timer->arg);
}
/**
* @brief Create a Timer
*/
osTimerId_t osTimerNew(osTimerFunc_t func, osTimerType_t type,
void *argument, const osTimerAttr_t *attr)
{
struct cv2_timer *timer;
if (type != osTimerOnce && type != osTimerPeriodic) {
return NULL;
}
if (k_is_in_isr()) {
return NULL;
}
if (attr == NULL) {
attr = &init_timer_attrs;
}
if (k_mem_slab_alloc(&cv2_timer_slab, (void **)&timer, 100) == 0) {
(void)memset(timer, 0, sizeof(struct cv2_timer));
} else {
return NULL;
}
timer->callback_function = func;
timer->arg = argument;
timer->type = type;
timer->status = NOT_ACTIVE;
k_timer_init(&timer->z_timer, zephyr_timer_wrapper, NULL);
if (attr->name == NULL) {
strncpy(timer->name, init_timer_attrs.name,
sizeof(timer->name) - 1);
} else {
strncpy(timer->name, attr->name, sizeof(timer->name) - 1);
}
return (osTimerId_t)timer;
}
/**
* @brief Start or restart a Timer
*/
osStatus_t osTimerStart(osTimerId_t timer_id, uint32_t ticks)
{
struct cv2_timer *timer = (struct cv2_timer *)timer_id;
u32_t millisec = __ticks_to_ms(ticks);
if (timer == NULL) {
return osErrorParameter;
}
if (k_is_in_isr()) {
return osErrorISR;
}
if (timer->type == osTimerOnce) {
k_timer_start(&timer->z_timer, millisec, 0);
} else if (timer->type == osTimerPeriodic) {
k_timer_start(&timer->z_timer, 0, millisec);
}
timer->status = ACTIVE;
return osOK;
}
/**
* @brief Stop the Timer
*/
osStatus_t osTimerStop(osTimerId_t timer_id)
{
struct cv2_timer *timer = (struct cv2_timer *)timer_id;
if (timer == NULL) {
return osErrorParameter;
}
if (k_is_in_isr()) {
return osErrorISR;
}
if (timer->status == NOT_ACTIVE) {
return osErrorResource;
}
k_timer_stop(&timer->z_timer);
timer->status = NOT_ACTIVE;
return osOK;
}
/**
* @brief Delete the timer that was created by osTimerCreate
*/
osStatus_t osTimerDelete(osTimerId_t timer_id)
{
struct cv2_timer *timer = (struct cv2_timer *) timer_id;
if (timer == NULL) {
return osErrorParameter;
}
if (k_is_in_isr()) {
return osErrorISR;
}
if (timer->status == ACTIVE) {
k_timer_stop(&timer->z_timer);
timer->status = NOT_ACTIVE;
}
k_mem_slab_free(&cv2_timer_slab, (void *) &timer);
return osOK;
}
/**
* @brief Get name of a timer.
*/
const char *osTimerGetName(osTimerId_t timer_id)
{
struct cv2_timer *timer = (struct cv2_timer *)timer_id;
if (k_is_in_isr() || (timer == NULL)) {
return NULL;
}
return timer->name;
}
/**
* @brief Check if a timer is running.
*/
uint32_t osTimerIsRunning(osTimerId_t timer_id)
{
struct cv2_timer *timer = (struct cv2_timer *)timer_id;
if (k_is_in_isr() || (timer == NULL)) {
return 0;
}
return !(!(k_timer_remaining_get(&timer->z_timer)));
}