<commit_before>/*
 * Copyright (c) 2009 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.
 */

#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <alloca.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

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

#include "transparent.h"

nmsg_res
_nmsg_msgmod_pres_to_payload(struct nmsg_msgmod *mod, void *cl, const char *pres) {
	ProtobufCMessage *m;
	char *line = NULL, *name = NULL, *saveptr = NULL;
	const char *value = NULL;
	int *qptr;
	nmsg_res res;
	size_t len;
	struct nmsg_msgmod_clos *clos = (struct nmsg_msgmod_clos *) cl;
	struct nmsg_msgmod_field *field = NULL;
	void *ptr;

	/* initialize the in-memory protobuf message if necessary */
	if (clos->nmsg_pbuf == NULL) {
		ProtobufCMessage *base;

		clos->nmsg_pbuf = calloc(1, mod->pbdescr->sizeof_message);
		if (clos->nmsg_pbuf == NULL) {
			return (nmsg_res_memfail);
		}
		base = (ProtobufCMessage *) &(clos->nmsg_pbuf)[0];
		base->descriptor = mod->pbdescr;
		clos->mode = nmsg_msgmod_clos_m_keyval;
	}

	/* convenience reference */
	m = (ProtobufCMessage *) clos->nmsg_pbuf;

	/* return pbuf ready if the end-of-message marker was seen */
	if (pres[0] == '\n' && clos->mode == nmsg_msgmod_clos_m_keyval) {
		clos->mode = nmsg_msgmod_clos_m_keyval;
		return (nmsg_res_pbuf_ready);
	}

	/* single line data types, and the type tag of a multiline string */
	if (clos->mode == nmsg_msgmod_clos_m_keyval) {
		/* make a copy of the line */
		len = strlen(pres);
		line = alloca(len);
		memcpy(line, pres, len);

		/* trim the newline at the end of the line */
		if (line[len - 1] == '\n')
			line[len - 1] = '\0';

		/* find the key */
		name = strtok_r(line, ":", &saveptr);
		if (name == NULL)
			return (nmsg_res_parse_error);

		/* find the field named by this key */
		for (field = mod->fields; field->descr != NULL; field++) {
			if (strcmp(name, field->descr->name) == 0)
				break;
		}

		if (field->descr == NULL)
			return (nmsg_res_parse_error);

		/* find the value */
		if (field->type != nmsg_msgmod_ft_mlstring)
			value = strtok_r(NULL, " ", &saveptr);

		/* reject truncated values */
		if (value == NULL)
			return (nmsg_res_parse_error);
	} else if (clos->mode == nmsg_msgmod_clos_m_multiline) {
		field = clos->field;
		value = pres;
	}

	/* load the value */
	if (PBFIELD_REPEATED(field)) {
		char **parray;
		int n;
		size_t bytes_needed, siz;

		parray = (char **) PBFIELD(m, field, void);
		qptr = PBFIELD_Q(m, field);
		siz = sizeof_elt_in_repeated_array(field->descr->type);
		bytes_needed = (*qptr + 1) * siz;

		n = *qptr;
		*qptr += 1;

		ptr = realloc(*parray, bytes_needed);
		if (ptr == NULL) {
			free(*parray);
			return (nmsg_res_memfail);
		}
		*parray = ptr;

		ptr = &((*parray)[n * siz]);
		memset(ptr, 0, siz);

		res = _nmsg_msgmod_pres_to_payload_load(field, clos, value, ptr, qptr);
		if (res != nmsg_res_success)
			return (res);
	} else {
		ptr = PBFIELD(m, field, void);
		qptr = PBFIELD_Q(m, field);

		res = _nmsg_msgmod_pres_to_payload_load(field, clos, value, ptr, qptr);
		if (res != nmsg_res_success)
			return (res);
	}
<commit_msg>transparent_pres: ensure consistent state after a realloc() failure<commit_after>/*
 * Copyright (c) 2009 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.
 */

#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <alloca.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

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

#include "transparent.h"

nmsg_res
_nmsg_msgmod_pres_to_payload(struct nmsg_msgmod *mod, void *cl, const char *pres) {
	ProtobufCMessage *m;
	char *line = NULL, *name = NULL, *saveptr = NULL;
	const char *value = NULL;
	int *qptr;
	nmsg_res res;
	size_t len;
	struct nmsg_msgmod_clos *clos = (struct nmsg_msgmod_clos *) cl;
	struct nmsg_msgmod_field *field = NULL;
	void *ptr;

	/* initialize the in-memory protobuf message if necessary */
	if (clos->nmsg_pbuf == NULL) {
		ProtobufCMessage *base;

		clos->nmsg_pbuf = calloc(1, mod->pbdescr->sizeof_message);
		if (clos->nmsg_pbuf == NULL) {
			return (nmsg_res_memfail);
		}
		base = (ProtobufCMessage *) &(clos->nmsg_pbuf)[0];
		base->descriptor = mod->pbdescr;
		clos->mode = nmsg_msgmod_clos_m_keyval;
	}

	/* convenience reference */
	m = (ProtobufCMessage *) clos->nmsg_pbuf;

	/* return pbuf ready if the end-of-message marker was seen */
	if (pres[0] == '\n' && clos->mode == nmsg_msgmod_clos_m_keyval) {
		clos->mode = nmsg_msgmod_clos_m_keyval;
		return (nmsg_res_pbuf_ready);
	}

	/* single line data types, and the type tag of a multiline string */
	if (clos->mode == nmsg_msgmod_clos_m_keyval) {
		/* make a copy of the line */
		len = strlen(pres);
		line = alloca(len);
		memcpy(line, pres, len);

		/* trim the newline at the end of the line */
		if (line[len - 1] == '\n')
			line[len - 1] = '\0';

		/* find the key */
		name = strtok_r(line, ":", &saveptr);
		if (name == NULL)
			return (nmsg_res_parse_error);

		/* find the field named by this key */
		for (field = mod->fields; field->descr != NULL; field++) {
			if (strcmp(name, field->descr->name) == 0)
				break;
		}

		if (field->descr == NULL)
			return (nmsg_res_parse_error);

		/* find the value */
		if (field->type != nmsg_msgmod_ft_mlstring)
			value = strtok_r(NULL, " ", &saveptr);

		/* reject truncated values */
		if (value == NULL)
			return (nmsg_res_parse_error);
	} else if (clos->mode == nmsg_msgmod_clos_m_multiline) {
		field = clos->field;
		value = pres;
	}

	/* load the value */
	if (PBFIELD_REPEATED(field)) {
		char **parray;
		int n;
		size_t bytes_needed, siz;

		parray = (char **) PBFIELD(m, field, void);
		qptr = PBFIELD_Q(m, field);
		siz = sizeof_elt_in_repeated_array(field->descr->type);
		bytes_needed = (*qptr + 1) * siz;

		n = *qptr;
		*qptr += 1;

		ptr = realloc(*parray, bytes_needed);
		if (ptr == NULL) {
			free(*parray);
			*qptr = 0;
			*parray = NULL;
			return (nmsg_res_memfail);
		}
		*parray = ptr;

		ptr = &((*parray)[n * siz]);
		memset(ptr, 0, siz);

		res = _nmsg_msgmod_pres_to_payload_load(field, clos, value, ptr, qptr);
		if (res != nmsg_res_success)
			return (res);
	} else {
		ptr = PBFIELD(m, field, void);
		qptr = PBFIELD_Q(m, field);

		res = _nmsg_msgmod_pres_to_payload_load(field, clos, value, ptr, qptr);
		if (res != nmsg_res_success)
			return (res);
	}

{'fraction_non_alphanumeric': 0.13409764266391858, 'fraction_numerical': 0.0037356692000515266, 'mean_word_length': 3.8163771712158807, 'pattern_counts': {'":': 2, '<': 17, '<?xml version=': 0, '>': 63, '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': '7224182', 'n_tokens_mistral': 3083, 'n_tokens_neox': 2813, 'n_words': 829}