static uint32 data_element_get_size (unsigned des, const uint8 **buf, uint32 *len, void (*handle_element) (unsigned type, const uint8 *buf, uint32 len))
{
    uint32 size;
#define DATA_ELEMENT_A_BAD_SIZE ((uint32) -1)

    switch (des)
    {
    case DATA_ELEMENT_SIZE_A8:
        if (*len < 1)
        {
            data_element_errno = DATA_ELEMENT_ERROR_TRUNCATED;
            handle_element (DATA_ELEMENT_ERROR_TRUNCATED, NULL, 0);
            return DATA_ELEMENT_A_BAD_SIZE;
        }
        ++*buf;
        --*len;
        *len -= 1;
        size = *(*buf)++;
        return size;

    case DATA_ELEMENT_SIZE_A16:
        if (*len < 2)
        {
            data_element_errno = DATA_ELEMENT_ERROR_TRUNCATED;
            handle_element (DATA_ELEMENT_ERROR_TRUNCATED, NULL, 1);
            return DATA_ELEMENT_A_BAD_SIZE;
        }
        ++*buf;
        --*len;
        *len -= 2;
        size = *(*buf)++;
        size <<= 8;
        size |= *(*buf)++;
        return size;

    case DATA_ELEMENT_SIZE_A32:
        if (*len < 4)
        {
            data_element_errno = DATA_ELEMENT_ERROR_TRUNCATED;
            handle_element (DATA_ELEMENT_ERROR_TRUNCATED, NULL, 2);
            return DATA_ELEMENT_A_BAD_SIZE;
        }
        ++*buf;
        --*len;
        *len -= 4;
        size = *(*buf)++;
        size <<= 8;
        size |= *(*buf)++;
        size <<= 8;
        size |= *(*buf)++;
        size <<= 8;
        size |= *(*buf)++;
        return size;
    }

    data_element_errno = DATA_ELEMENT_ERROR_INTERNAL;
    handle_element (DATA_ELEMENT_ERROR_INTERNAL, NULL, 0);
    return DATA_ELEMENT_A_BAD_SIZE;
}
示例#2
0
static void on_end_element(GMarkupParseContext *context,
        const gchar *element_name,
        gpointer user_data, GError **error) {
    debug_printf("on_end_element %s\n", element_name);

    if (strcmp(element_name, "fragment") == 0) {
    }
    else if (strcmp(element_name, "vertex") == 0) {
    }
    else {
        return;
    }

    parse_data *data = user_data;
    data->buffer[data->length] = 0;
    if (data->error) {

    }
    else {
        debug_printf("%s\n", data->buffer);
        handle_element(data, element_name, data->buffer);
    }
    if (data->filter) {
        g_free(data->filter);
        data->filter = NULL;
    }
}
static void data_element_decode_internal (const uint8 **buf, uint32 *len, void (*handle_element) (unsigned type, const uint8 *buf, uint32 len))
{
    unsigned des, det;
    uint32 size;

    if (*len == 0)
    {
        data_element_errno = DATA_ELEMENT_ERROR_TRUNCATED;
        handle_element (DATA_ELEMENT_ERROR_TRUNCATED, NULL, 3);
    }
    else
    {
        det = DATA_ELEMENT_TYPE (**buf);
        des = DATA_ELEMENT_SIZE (**buf);
        switch (det)
        {
        case DATA_ELEMENT_TYPE_NIL:
            if (des != DATA_ELEMENT_SIZE_1)
            {
                data_element_errno = DATA_ELEMENT_ERROR_INVALID;
                handle_element (DATA_ELEMENT_ERROR_INVALID, NULL, 0);
            }
            else
            {
                ++*buf;
                --*len;
                handle_element (det, NULL, 0);
            }
            break;

        case DATA_ELEMENT_TYPE_UUID:
            if (des != DATA_ELEMENT_SIZE_2 &&
                des != DATA_ELEMENT_SIZE_4 &&
                des != DATA_ELEMENT_SIZE_16)
            {
                data_element_errno = DATA_ELEMENT_ERROR_INVALID;
                handle_element (DATA_ELEMENT_ERROR_INVALID, NULL, 0);
                break;
            }
            /* Deliberate fall-through */
        case DATA_ELEMENT_TYPE_UINT:
        case DATA_ELEMENT_TYPE_INT:
            if (des > DATA_ELEMENT_SIZE_16)
            {
                data_element_errno = DATA_ELEMENT_ERROR_INVALID;
                handle_element (DATA_ELEMENT_ERROR_INVALID, NULL, 0);
            }
            else
            {
                size = 1 << des;
                if (*len < 1 + size)
                {
                    data_element_errno = DATA_ELEMENT_ERROR_TRUNCATED;
                    handle_element (DATA_ELEMENT_ERROR_TRUNCATED, NULL, 4);
                }
                else
                {
                    ++*buf;
                    --*len;
                    handle_element (det, *buf, size);
                    *buf += size;
                    *len -= size;
                }
            }
            break;

        case DATA_ELEMENT_TYPE_TEXT:
        case DATA_ELEMENT_TYPE_URL:
            if (des < DATA_ELEMENT_SIZE_A8)
            {
                data_element_errno = DATA_ELEMENT_ERROR_INVALID;
                handle_element (DATA_ELEMENT_ERROR_INVALID, NULL, 0);
            }
            else
            {
                uint32 save_len = *len;

                if ((size = data_element_get_size (des, buf, len, handle_element)) != DATA_ELEMENT_A_BAD_SIZE)
                {
                    if (*len < size)
                    {
                        *buf -= save_len - *len;
                        *len = save_len;
                        data_element_errno = DATA_ELEMENT_ERROR_TRUNCATED;
                        handle_element (DATA_ELEMENT_ERROR_TRUNCATED, NULL, 5);
                    }
                    else
                    {
                        handle_element (det, *buf, size);
                        *buf += size;
                        *len -= size;
                    }
                }
            }
            break;

        case DATA_ELEMENT_TYPE_BOOL:
            if (des != DATA_ELEMENT_SIZE_1)
            {
                data_element_errno = DATA_ELEMENT_ERROR_INVALID;
                handle_element (DATA_ELEMENT_ERROR_INVALID, NULL, 0);
            }
            else
            {
                if (*len < 2)
                {
                    data_element_errno = DATA_ELEMENT_ERROR_TRUNCATED;
                    handle_element (DATA_ELEMENT_ERROR_TRUNCATED, NULL, 6);
                }
                else
                {
                    ++*buf;
                    --*len;
                    handle_element (det, *buf, 1);
                    ++*buf;
                    --*len;
                }
            }
            break;

        case DATA_ELEMENT_TYPE_SEQ:
        case DATA_ELEMENT_TYPE_ALT:
            if (des < DATA_ELEMENT_SIZE_A8)
            {
                data_element_errno = DATA_ELEMENT_ERROR_INVALID;
                handle_element (DATA_ELEMENT_ERROR_INVALID, NULL, 0);
            }
            else
            {
                uint32 save_len = *len;

                if ((size = data_element_get_size (des, buf, len, handle_element)) != DATA_ELEMENT_A_BAD_SIZE)
                {
                    if (*len < size)
                    {
                        *buf -= save_len - *len;
                        *len = save_len;
                        data_element_errno = DATA_ELEMENT_ERROR_TRUNCATED;
                        handle_element (DATA_ELEMENT_ERROR_TRUNCATED, NULL, 7);
                    }
                    else
                    {
                        save_len = *len;
                        handle_element (det | DATA_ELEMENT_TYPE_START, NULL, 0);
                        while (save_len - *len != size)
                        {
                            data_element_decode (buf, len, handle_element);
                            if (data_element_errno)
                            {
                                break;
                            }
                            if (save_len - *len != size)
                            {
                                handle_element (det | DATA_ELEMENT_TYPE_SEPARATOR, NULL, 0);
                            }
                        }
                        handle_element (det | DATA_ELEMENT_TYPE_END, NULL, 0);
                    }
                }
            }
            break;

        default:
            data_element_errno = DATA_ELEMENT_ERROR_INVALID;
            handle_element (DATA_ELEMENT_ERROR_INVALID, NULL, 0);
            break;
        }
    }
}
	CInterfaceDefinition *CInterfaceDefinitionLoader::load( const unsigned char &buffer, unsigned int buffer_size )
	{
		assert( !m_interface_definition && !m_reader && m_element_path.empty() );

		m_interface_definition = new CInterfaceDefinition;

		xmlInitParser();

		m_reader = xmlReaderForMemory( (char *) &buffer, buffer_size, NULL, NULL, 0 );
		if( !m_reader )
		{
			INTEGRA_TRACE_ERROR << "unable to read file";
			cleanup();
			return NULL;
		}

		int depth = -1;
		bool handled_element_content = false;
		char *inner_xml = NULL; 

		while( xmlTextReaderRead( m_reader ) )
		{
			switch( xmlTextReaderNodeType( m_reader ) )
			{
				case XML_READER_TYPE_TEXT:
					{
						char *element_value = ( char * ) xmlTextReaderValue( m_reader );
						if( handle_element_value( element_value ) != CError::SUCCESS )
						{
							xmlFree( element_value );
							cleanup();
							return NULL;
						}
						xmlFree( element_value );
						handled_element_content = true;

						store_map_entries();
					}
					break;

				case XML_READER_TYPE_ELEMENT:
					{
						const char *element_name = ( const char * ) xmlTextReaderConstName( m_reader );
						int new_depth = xmlTextReaderDepth( m_reader );

						while( depth >= new_depth )
						{
							pop_element_name();
							depth--;
						}

						if( depth < new_depth )
						{
							push_element_name( element_name );
							depth++;
						}

						assert( depth == new_depth );

						if( handle_element() != CError::SUCCESS )
						{
							cleanup();
							return NULL;
						}

						if( xmlTextReaderHasAttributes( m_reader ) )
						{
							if( handle_element_attributes() != CError::SUCCESS )
							{
								cleanup();
								return NULL;
							}
						}

						if( xmlTextReaderIsEmptyElement( m_reader ) )
						{
							handle_element_value( "" );
							handled_element_content = true;
						}
						else
						{
							handled_element_content = false;
							inner_xml = ( char * ) xmlTextReaderReadInnerXml( m_reader );
						}
					}

					break;

				case XML_READER_TYPE_END_ELEMENT:
					if( !handled_element_content && inner_xml )
					{
						handle_element_value( inner_xml );
					}
					if( inner_xml )
					{
						xmlFree( inner_xml );
						inner_xml = NULL;
					}
					handled_element_content = true;
					break;

				default:
					break;
			}
		}

		CError CError = do_sanity_check();
		if( CError != CError::SUCCESS )
		{
			INTEGRA_TRACE_ERROR << "sanity check failed";
			cleanup();
			return NULL;
		}

		m_interface_definition->propagate_defaults();

		INTEGRA_TRACE_VERBOSE << "Loaded ok: " << m_interface_definition->get_interface_info().get_name();
		CInterfaceDefinition *loaded_interface = m_interface_definition;
		m_interface_definition = NULL;
		cleanup();

		return loaded_interface;
	}