Exemplo n.º 1
0
void
lwmsg_type_iterate_promoted(
    LWMsgTypeSpec* spec,
    LWMsgTypeIter* iter
    )
{
    switch (*spec & LWMSG_CMD_MASK)
    {
    case LWMSG_CMD_POINTER:
        lwmsg_type_iterate(spec, iter);
        break;
    case LWMSG_CMD_CUSTOM:
        lwmsg_type_iterate(spec, iter);
        if (!iter->info.kind_custom.typeclass->is_pointer)
        {
            lwmsg_type_promote(spec, iter);
        }
        break;
    default:
        lwmsg_type_promote(spec, iter);
        break;
    }
}
Exemplo n.º 2
0
LWMsgStatus
lwmsg_data_unmarshal_into(
    LWMsgDataContext* context,
    LWMsgTypeSpec* type,
    LWMsgBuffer* buffer,
    void* object,
    size_t size
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;
    LWMsgObjectMap map;
    LWMsgUnmarshalState my_state = {NULL, &map};
    LWMsgTypeIter iter;

    memset(&map, 0, sizeof(map));

    lwmsg_type_iterate(type, &iter);

    if (size < iter.size)
    {
        BAIL_ON_ERROR(status = LWMSG_STATUS_BUFFER_TOO_SMALL);
    }

    BAIL_ON_ERROR(status = lwmsg_data_unmarshal_internal(context, &my_state, &iter, buffer, object));

    if (buffer->wrap)
    {
        BAIL_ON_ERROR(status = buffer->wrap(buffer, 0));
    }

error:

    lwmsg_data_object_map_destroy(&map);

    return status;
}
Exemplo n.º 3
0
static LWMsgStatus
lwmsg_data_unmarshal_struct_pointee(
    LWMsgDataContext* context,
    LWMsgUnmarshalState* state,
    LWMsgTypeIter* pointer_iter,
    LWMsgTypeIter* struct_iter,
    LWMsgBuffer* buffer,
    unsigned char** out
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;
    unsigned char* base_object = NULL;
    unsigned char* full_object = NULL;
    LWMsgTypeSpec* flexible_member = NULL;
    size_t base_size = 0;
    size_t full_size = 0;
    LWMsgObjectID id = 0;

    base_size = struct_iter->size;

    if (pointer_iter->attrs.flags & LWMSG_TYPE_FLAG_ALIASABLE &&
        base_size < sizeof(void*))
    {
        base_size = sizeof(void*);
    }

    /* Enforce MAX_ALLOC attribute */
    if (pointer_iter->attrs.max_alloc && base_size > pointer_iter->attrs.max_alloc)
    {
        BAIL_ON_ERROR(status = DATA_RAISE(
                     context,
                     pointer_iter,
                     LWMSG_STATUS_OVERFLOW,
                     "Pointer referent exceeded max allocation size of %lu",
                     (unsigned long) pointer_iter->attrs.max_alloc));
    }

    /* Allocate enough memory to hold the base of the object */
    BAIL_ON_ERROR(status = lwmsg_object_alloc(
                      context,
                      base_size,
                      &base_object));

    if (pointer_iter->attrs.flags & LWMSG_TYPE_FLAG_ALIASABLE)
    {
        /* If this is the referent of an aliasable pointer, insert it into the object map now */
        BAIL_ON_ERROR(status = lwmsg_data_object_map_insert(
                          state->map,
                          base_object,
                          pointer_iter,
                          &id));
    }

    /* Unmarshal all base members of the structure and find any flexible member */
    BAIL_ON_ERROR(status = lwmsg_data_unmarshal_struct(
                      context,
                      state,
                      struct_iter,
                      buffer,
                      base_object,
                      &flexible_member));

    /* Now that the base of the object is unmarshalled, we can see if we need to
       reallocate space for a flexible member */
    if (flexible_member)
    {
        LWMsgTypeIter flex_iter;
        LWMsgTypeIter inner_iter;
        LWMsgUnmarshalState my_state = {base_object, state->map};
        size_t count = 0;
        size_t full_count = 0;
        size_t flexible_size = 0;

        lwmsg_type_iterate(flexible_member, &flex_iter);
        lwmsg_type_enter(&flex_iter, &inner_iter);

        BAIL_ON_ERROR(status = lwmsg_data_unmarshal_indirect_prologue(
                          context,
                          &my_state,
                          &flex_iter,
                          &inner_iter,
                          buffer,
                          &count));

        /* Calculate total number of elements */
        if (flex_iter.info.kind_indirect.term == LWMSG_TERM_ZERO)
        {
            /* If the referent is zero-terminated, we need to allocate an extra element */
            BAIL_ON_ERROR(status = DATA_RAISE(
                            context,
                            pointer_iter,
                            lwmsg_add_unsigned(count, 1, &full_count),
                            "Integer overflow in pointer referent length"));
        }
        else
        {
            full_count = count;
        }

        /* Calculate the size of the flexible member */
        BAIL_ON_ERROR(status = DATA_RAISE(
                        context,
                        pointer_iter,
                        lwmsg_multiply_unsigned(full_count, inner_iter.size, &flexible_size),
                        "Integer overflow in pointer referent size"));

        /* Calculate the size of the full structure */
        BAIL_ON_ERROR(status = DATA_RAISE(
                        context,
                        pointer_iter,
                        lwmsg_add_unsigned(struct_iter->size, flexible_size, &full_size),
                        "Integer overflow in pointer referent size"));

        if (pointer_iter->attrs.flags & LWMSG_TYPE_FLAG_ALIASABLE &&
            full_size < sizeof(void*))
        {
            full_size = sizeof(void*);
        }

        /* Enforce MAX_ALLOC attribute */
        if (pointer_iter->attrs.max_alloc && full_size > pointer_iter->attrs.max_alloc)
        {
            BAIL_ON_ERROR(status = DATA_RAISE(
                         context,
                         pointer_iter,
                         LWMSG_STATUS_OVERFLOW,
                         "Pointer referent exceeded max allocation size of %lu",
                         (unsigned long) pointer_iter->attrs.max_alloc));
        }

        /* Allocate the full object */
        BAIL_ON_ERROR(status = lwmsg_object_realloc(
                          context,
                          base_object,
                          struct_iter->size,
                          full_size,
                          &full_object));

        base_object = NULL;

        /* Unmarshal the flexible array member */
        BAIL_ON_ERROR(status = lwmsg_data_unmarshal_indirect(
                          context,
                          &my_state,
                          &flex_iter,
                          &inner_iter,
                          buffer,
                          full_object + flex_iter.offset,
                          count));
    }
    else
    {
        full_object = base_object;
        base_object = NULL;
    }

    *out = full_object;

done:

    return status;

error:

    if (base_object)
    {
        /* We must avoid visiting flexible array members when
           freeing the base object because it does not have
           space for them in the allocated block */
        lwmsg_data_unmarshal_free_partial_struct(
            context,
            struct_iter,
            base_object);
    }

    if (full_object)
    {
        lwmsg_data_free_graph_internal(context, pointer_iter, (unsigned char*) &base_object);
    }

    goto done;
}
Exemplo n.º 4
0
static LWMsgStatus
lwmsg_data_unmarshal_custom(
    LWMsgDataContext* context,
    LWMsgUnmarshalState* state,
    LWMsgTypeIter* iter,
    LWMsgBuffer* buffer,
    unsigned char* object
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;
    LWMsgTypeClass* typeclass = iter->info.kind_custom.typeclass;
    LWMsgTypeIter transmit_iter;
    void* transmit_object = NULL;
    LWMsgUnmarshalState my_state = {NULL, state->map};

    lwmsg_type_iterate(typeclass->transmit_type, &transmit_iter);

    if (typeclass->unmarshal)
    {
        /* Allocate memory for transmitted object */
        BAIL_ON_ERROR(status = lwmsg_data_alloc_memory(context, transmit_iter.size, &transmit_object));

        /* Unmarshal transmitted object */
        BAIL_ON_ERROR(status = lwmsg_data_unmarshal_internal(
            context,
            &my_state,
            &transmit_iter,
            buffer,
            transmit_object));

        /* Convert transmitted object into presented object */
        BAIL_ON_ERROR(status = iter->info.kind_custom.typeclass->unmarshal(
            context,
            &iter->attrs,
            transmit_object,
            object,
            iter->info.kind_custom.typedata));
    }
    else
    {
        /* Just unmarshal the transmitted type */
        BAIL_ON_ERROR(status = lwmsg_data_unmarshal_internal(
            context,
            state,
            &transmit_iter,
            buffer,
            object));
    }

error:

    if (transmit_object)
    {
        /* Since we constructed the transmitted object ourselves, we do not call
           the destroy_transmitted function of the type class */
        lwmsg_data_free_graph_internal(context, &transmit_iter, transmit_object);
        /* Free object itself */
        lwmsg_data_free_memory(context, transmit_object);
    }

    return status;
}