Browse Source

[Fix] Backport fix for empty files inclusion from libucl

Issue: #596
Reported by: @assistcontrol
pull/598/head
Vsevolod Stakhov 10 years ago
parent
commit
f789d85b3a
  1. 22
      contrib/libucl/ucl.h
  2. 61
      contrib/libucl/ucl_parser.c
  3. 50
      contrib/libucl/ucl_util.c

22
contrib/libucl/ucl.h

@ -107,7 +107,8 @@ typedef enum ucl_error {
UCL_ENESTED, /**< Input has too many recursion levels */
UCL_EMACRO, /**< Error processing a macro */
UCL_EINTERNAL, /**< Internal unclassified error */
UCL_ESSL /**< SSL error */
UCL_ESSL, /**< SSL error */
UCL_EMERGE /**< A merge error occured */
} ucl_error_t;
/**
@ -1130,6 +1131,25 @@ UCL_EXTERN const ucl_object_t * ucl_parser_get_comments (struct ucl_parser *pars
UCL_EXTERN const ucl_object_t * ucl_comments_find (const ucl_object_t *comments,
const ucl_object_t *srch);
/**
* Move comment from `from` object to `to` object
* @param comments comments object
* @param what source object
* @param whith destination object
* @return `true` if `from` has comment and it has been moved to `to`
*/
UCL_EXTERN bool ucl_comments_move (ucl_object_t *comments,
const ucl_object_t *from, const ucl_object_t *to);
/**
* Adds a new comment for an object
* @param comments comments object
* @param obj object to add comment to
* @param comment string representation of a comment
*/
UCL_EXTERN void ucl_comments_add (ucl_object_t *comments,
const ucl_object_t *obj, const char *comment);
/**
* Add new public key to parser for signatures check
* @param parser parser object

61
contrib/libucl/ucl_parser.c

@ -1068,6 +1068,7 @@ ucl_parser_process_object_element (struct ucl_parser *parser, ucl_object_t *nobj
{
ucl_hash_t *container;
ucl_object_t *tobj;
char errmsg[256];
container = parser->stack->obj->value.ov;
@ -1126,25 +1127,36 @@ ucl_parser_process_object_element (struct ucl_parser *parser, ucl_object_t *nobj
break;
case UCL_DUPLICATE_ERROR:
ucl_create_err (&parser->err, "error while parsing %s: "
"line: %d, column: %d: duplicate element for key '%s' "
"has been found",
parser->cur_file ? parser->cur_file : "<unknown>",
parser->chunks->line, parser->chunks->column, nobj->key);
snprintf(errmsg, sizeof(errmsg),
"duplicate element for key '%s' found",
nobj->key);
ucl_set_err (parser, UCL_EMERGE, errmsg, &parser->err);
return false;
case UCL_DUPLICATE_MERGE:
/*
* Here we do have some old object so we just push it on top of objects stack
* Check priority and then perform the merge on the remaining objects
*/
if (tobj->type == UCL_OBJECT || tobj->type == UCL_ARRAY) {
ucl_object_unref (nobj);
nobj = tobj;
}
else {
/* For other types we create implicit array as usual */
else if (priold == prinew) {
ucl_parser_append_elt (parser, container, tobj, nobj);
}
else if (priold > prinew) {
/*
* We add this new object to a list of trash objects just to ensure
* that it won't come to any real object
* XXX: rather inefficient approach
*/
DL_APPEND (parser->trash_objs, nobj);
}
else {
ucl_hash_replace (container, tobj, nobj);
ucl_object_unref (tobj);
}
break;
}
}
@ -2585,20 +2597,18 @@ ucl_parser_add_chunk_full (struct ucl_parser *parser, const unsigned char *data,
return false;
}
if (data == NULL) {
if (data == NULL && len != 0) {
ucl_create_err (&parser->err, "invalid chunk added");
return false;
}
if (len == 0) {
parser->top_obj = ucl_object_new_full (UCL_OBJECT, priority);
return true;
}
if (parser->state != UCL_STATE_ERROR) {
chunk = UCL_ALLOC (sizeof (struct ucl_chunk));
if (chunk == NULL) {
ucl_create_err (&parser->err, "cannot allocate chunk structure");
return false;
}
chunk->begin = data;
chunk->remain = len;
chunk->pos = chunk->begin;
@ -2617,12 +2627,27 @@ ucl_parser_add_chunk_full (struct ucl_parser *parser, const unsigned char *data,
return false;
}
switch (parse_type) {
default:
case UCL_PARSE_UCL:
return ucl_state_machine (parser);
case UCL_PARSE_MSGPACK:
return ucl_parse_msgpack (parser);
if (len > 0) {
/* Need to parse something */
switch (parse_type) {
default:
case UCL_PARSE_UCL:
return ucl_state_machine (parser);
case UCL_PARSE_MSGPACK:
return ucl_parse_msgpack (parser);
}
}
else {
/* Just add empty chunk and go forward */
if (parser->top_obj == NULL) {
/*
* In case of empty object, create one to indicate that we've
* read something
*/
parser->top_obj = ucl_object_new_full (UCL_OBJECT, priority);
}
return true;
}
}

50
contrib/libucl/ucl_util.c

@ -975,6 +975,7 @@ ucl_include_file_single (const unsigned char *data, size_t len,
if (params->soft_fail) {
return false;
}
return (!params->must_exist || false);
}
@ -1172,11 +1173,14 @@ ucl_include_file_single (const unsigned char *data, size_t len,
res = ucl_parser_add_chunk_full (parser, buf, buflen, params->priority,
params->strat, params->parse_type);
if (!res && !params->must_exist) {
/* Free error */
utstring_free (parser->err);
parser->err = NULL;
parser->state = UCL_STATE_AFTER_VALUE;
if (!res) {
if (!params->must_exist) {
/* Free error */
utstring_free (parser->err);
parser->err = NULL;
res = true;
}
}
/* Stop nesting the include, take 1 level off the stack */
@ -3450,3 +3454,39 @@ ucl_comments_find (const ucl_object_t *comments,
return NULL;
}
bool
ucl_comments_move (ucl_object_t *comments,
const ucl_object_t *from, const ucl_object_t *to)
{
const ucl_object_t *found;
ucl_object_t *obj;
if (comments && from && to) {
found = ucl_object_lookup_len (comments,
(const char *)&from, sizeof (void *));
if (found) {
/* Replace key */
obj = ucl_object_ref (found);
ucl_object_delete_keyl (comments, (const char *)&from,
sizeof (void *));
ucl_object_insert_key (comments, obj, (const char *)&to,
sizeof (void *), true);
return true;
}
}
return false;
}
void
ucl_comments_add (ucl_object_t *comments, const ucl_object_t *obj,
const char *comment)
{
if (comments && obj && comment) {
ucl_object_insert_key (comments, ucl_object_fromstring (comment),
(const char *)&obj, sizeof (void *), true);
}
}
Loading…
Cancel
Save