<commit_before>/*
 * Copyright (c) 2009, 2010 by Internet Systems Consortium, Inc. ("ISC")
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/* Import. */

#include "nmsg_port.h"

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

#include "nmsg.h"
#include "private.h"

#include "transparent.h"

/* Macros. */

#define CHECK_TRANSPARENT() do { \
	if (msg->mod == NULL || msg->mod->plugin == NULL || \
	    msg->mod->plugin->type != nmsg_msgmod_type_transparent || \
	    msg->mod->plugin->pbdescr == NULL) \
		return (nmsg_res_failure); \
} while(0);

#define DESERIALIZE() do { \
	nmsg_res c_t_res; \
	c_t_res = _nmsg_message_deserialize(msg); \
	if (c_t_res != nmsg_res_success) \
		return (c_t_res); \
} while(0);

#define GET_FIELD(idx) do { \
	if (field_idx > msg->mod->n_fields - 1) \
		return (nmsg_res_failure); \
	field = &msg->mod->fields[field_idx]; \
} while(0);

/* Export: getters. */

nmsg_res
nmsg_message_get_num_fields(struct nmsg_message *msg, size_t *n_fields) {
	CHECK_TRANSPARENT();
	*n_fields = msg->mod->n_fields;
	return (nmsg_res_success);
}

nmsg_res
nmsg_message_get_field_name(struct nmsg_message *msg, unsigned field_idx,
			    const char **field_name)
{
	struct nmsg_msgmod_field *field;
	CHECK_TRANSPARENT();
	GET_FIELD(field_idx);
	*field_name = field->name;
	return (nmsg_res_success);
}

nmsg_res
nmsg_message_get_field_idx(struct nmsg_message *msg, const char *field_name,
			   unsigned *idx)
{
	struct nmsg_msgmod_field *field;
	CHECK_TRANSPARENT();

	field = _nmsg_msgmod_lookup_field(msg->mod, field_name);
	if (field == NULL)
		return (nmsg_res_failure);

	*idx = field - &msg->mod->fields[0];
	return (nmsg_res_success);
}

nmsg_res
nmsg_message_get_field_flags_by_idx(struct nmsg_message *msg,
				    unsigned field_idx,
				    unsigned *flags)
{
	struct nmsg_msgmod_field *field;
	CHECK_TRANSPARENT();
	GET_FIELD(field_idx);
	*flags = field->flags;
	return (nmsg_res_success);
}

nmsg_res
nmsg_message_get_field_flags(struct nmsg_message *msg,
			     const char *field_name,
			     unsigned *flags)
{
	nmsg_res res;
	unsigned field_idx;

	res = nmsg_message_get_field_idx(msg, field_name, &field_idx);
	if (res == nmsg_res_success)
		return (nmsg_message_get_field_flags_by_idx(msg, field_idx, flags));
	else
		return (nmsg_res_failure);
}

nmsg_res
nmsg_message_get_field_type_by_idx(struct nmsg_message *msg,
				   unsigned field_idx,
				   nmsg_msgmod_field_type *type)
{
	struct nmsg_msgmod_field *field;
	CHECK_TRANSPARENT();
	GET_FIELD(field_idx);
	*type = field->type;
	return (nmsg_res_success);
}

nmsg_res
nmsg_message_get_field_type(struct nmsg_message *msg,
			    const char *field_name,
			    nmsg_msgmod_field_type *type)
{
	nmsg_res res;
	unsigned field_idx;

	res = nmsg_message_get_field_idx(msg, field_name, &field_idx);
	if (res == nmsg_res_success)
		return (nmsg_message_get_field_type_by_idx(msg, field_idx, type));
	else
		return (nmsg_res_failure);
}

nmsg_res
nmsg_message_get_field_by_idx(nmsg_message_t msg, unsigned field_idx,
			      unsigned val_idx,
			      void **data, size_t *len)
{
	ProtobufCBinaryData *bdata;
	char **parray;
	int *qptr;
	size_t sz;
	struct nmsg_msgmod_field *field;
	void *ptr = NULL;

	CHECK_TRANSPARENT();
	GET_FIELD(field_idx);

	if (field->flags & NMSG_MSGMOD_FIELD_HIDDEN)
		return (nmsg_res_failure);

	DESERIALIZE();

	if (field->get != NULL)
		return (field->get(msg, field, val_idx, data, len, msg->msg_clos));

	qptr = PBFIELD_Q(msg->message, field);

	switch (field->descr->label) {
	case PROTOBUF_C_LABEL_REPEATED:
		sz = sizeof_elt_in_repeated_array(field->descr->type);

		if (val_idx >= (unsigned) *qptr) {
			return (nmsg_res_failure);
		}
		parray = (char **) PBFIELD(msg->message, field, void);
		ptr = *parray + (sz * val_idx);
		break;
	case PROTOBUF_C_LABEL_OPTIONAL:
		/* FALLTHROUGH */
	case PROTOBUF_C_LABEL_REQUIRED:
		if (val_idx > 0)
			return (nmsg_res_failure);
		ptr = PBFIELD(msg->message, field, void);
		break;
	}
<commit_msg>msgmod: add a missing val_idx check for optional fields in nmsg_message_get_field_by_idx()<commit_after>/*
 * Copyright (c) 2009, 2010 by Internet Systems Consortium, Inc. ("ISC")
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/* Import. */

#include "nmsg_port.h"

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

#include "nmsg.h"
#include "private.h"

#include "transparent.h"

/* Macros. */

#define CHECK_TRANSPARENT() do { \
	if (msg->mod == NULL || msg->mod->plugin == NULL || \
	    msg->mod->plugin->type != nmsg_msgmod_type_transparent || \
	    msg->mod->plugin->pbdescr == NULL) \
		return (nmsg_res_failure); \
} while(0);

#define DESERIALIZE() do { \
	nmsg_res c_t_res; \
	c_t_res = _nmsg_message_deserialize(msg); \
	if (c_t_res != nmsg_res_success) \
		return (c_t_res); \
} while(0);

#define GET_FIELD(idx) do { \
	if (field_idx > msg->mod->n_fields - 1) \
		return (nmsg_res_failure); \
	field = &msg->mod->fields[field_idx]; \
} while(0);

/* Export: getters. */

nmsg_res
nmsg_message_get_num_fields(struct nmsg_message *msg, size_t *n_fields) {
	CHECK_TRANSPARENT();
	*n_fields = msg->mod->n_fields;
	return (nmsg_res_success);
}

nmsg_res
nmsg_message_get_field_name(struct nmsg_message *msg, unsigned field_idx,
			    const char **field_name)
{
	struct nmsg_msgmod_field *field;
	CHECK_TRANSPARENT();
	GET_FIELD(field_idx);
	*field_name = field->name;
	return (nmsg_res_success);
}

nmsg_res
nmsg_message_get_field_idx(struct nmsg_message *msg, const char *field_name,
			   unsigned *idx)
{
	struct nmsg_msgmod_field *field;
	CHECK_TRANSPARENT();

	field = _nmsg_msgmod_lookup_field(msg->mod, field_name);
	if (field == NULL)
		return (nmsg_res_failure);

	*idx = field - &msg->mod->fields[0];
	return (nmsg_res_success);
}

nmsg_res
nmsg_message_get_field_flags_by_idx(struct nmsg_message *msg,
				    unsigned field_idx,
				    unsigned *flags)
{
	struct nmsg_msgmod_field *field;
	CHECK_TRANSPARENT();
	GET_FIELD(field_idx);
	*flags = field->flags;
	return (nmsg_res_success);
}

nmsg_res
nmsg_message_get_field_flags(struct nmsg_message *msg,
			     const char *field_name,
			     unsigned *flags)
{
	nmsg_res res;
	unsigned field_idx;

	res = nmsg_message_get_field_idx(msg, field_name, &field_idx);
	if (res == nmsg_res_success)
		return (nmsg_message_get_field_flags_by_idx(msg, field_idx, flags));
	else
		return (nmsg_res_failure);
}

nmsg_res
nmsg_message_get_field_type_by_idx(struct nmsg_message *msg,
				   unsigned field_idx,
				   nmsg_msgmod_field_type *type)
{
	struct nmsg_msgmod_field *field;
	CHECK_TRANSPARENT();
	GET_FIELD(field_idx);
	*type = field->type;
	return (nmsg_res_success);
}

nmsg_res
nmsg_message_get_field_type(struct nmsg_message *msg,
			    const char *field_name,
			    nmsg_msgmod_field_type *type)
{
	nmsg_res res;
	unsigned field_idx;

	res = nmsg_message_get_field_idx(msg, field_name, &field_idx);
	if (res == nmsg_res_success)
		return (nmsg_message_get_field_type_by_idx(msg, field_idx, type));
	else
		return (nmsg_res_failure);
}

nmsg_res
nmsg_message_get_field_by_idx(nmsg_message_t msg, unsigned field_idx,
			      unsigned val_idx,
			      void **data, size_t *len)
{
	ProtobufCBinaryData *bdata;
	char **parray;
	int *qptr;
	size_t sz;
	struct nmsg_msgmod_field *field;
	void *ptr = NULL;

	CHECK_TRANSPARENT();
	GET_FIELD(field_idx);

	if (field->flags & NMSG_MSGMOD_FIELD_HIDDEN)
		return (nmsg_res_failure);

	DESERIALIZE();

	if (field->get != NULL)
		return (field->get(msg, field, val_idx, data, len, msg->msg_clos));

	qptr = PBFIELD_Q(msg->message, field);

	switch (field->descr->label) {
	case PROTOBUF_C_LABEL_REPEATED:
		sz = sizeof_elt_in_repeated_array(field->descr->type);

		if (val_idx >= (unsigned) *qptr) {
			return (nmsg_res_failure);
		}
		parray = (char **) PBFIELD(msg->message, field, void);
		ptr = *parray + (sz * val_idx);
		break;
	case PROTOBUF_C_LABEL_OPTIONAL:
		if (val_idx >= (unsigned) *qptr)
			return (nmsg_res_failure);
		/* FALLTHROUGH */
	case PROTOBUF_C_LABEL_REQUIRED:
		if (val_idx > 0)
			return (nmsg_res_failure);
		ptr = PBFIELD(msg->message, field, void);
		break;
	}

{'fraction_non_alphanumeric': 0.11458992199030149, 'fraction_numerical': 0.0029517183217372973, 'mean_word_length': 4.663880597014925, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 82, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4718593', 'n_tokens_mistral': 3770, 'n_tokens_neox': 3538, 'n_words': 828}