From 45b3c756990b8bfe0ea799fb3a82b51865127451 Mon Sep 17 00:00:00 2001 From: Eivind Kvedalen Date: Tue, 28 Jun 2011 21:43:13 +0200 Subject: [PATCH] Partial fix for bug #700448. NULL is returned from o_*_read and o_read_buffer functions if parsing of the input buffer fails. An error object is returned in these cases, describing in detail what error occured. gnetlist is updated to exit with status code 2 if the input file can't be read. gschem is updated to report errors when using o_read_buffer. TODO: * Prone to segfaults on bad input files (separate patch) --- gnetlist/src/gnetlist.c | 1 + gschem/src/o_complex.c | 7 ++- gschem/src/x_clipboard.c | 10 ++- gschem/src/x_preview.c | 10 ++- libgeda/include/libgeda/edaerrors.h | 1 + libgeda/include/libgeda/prototype.h | 2 +- libgeda/include/prototype_priv.h | 25 +++--- libgeda/src/a_basic.c | 164 +++++++++++++++++++++-------------- libgeda/src/o_arc_basic.c | 22 +++-- libgeda/src/o_attrib.c | 54 +++++++---- libgeda/src/o_box_basic.c | 24 +++-- libgeda/src/o_bus_basic.c | 16 +++- libgeda/src/o_circle_basic.c | 29 ++++--- libgeda/src/o_complex_basic.c | 163 +++++++++++++++++----------------- libgeda/src/o_line_basic.c | 20 +++-- libgeda/src/o_net_basic.c | 9 ++- libgeda/src/o_path_basic.c | 23 +++-- libgeda/src/o_picture.c | 28 +++--- libgeda/src/o_pin_basic.c | 16 +++- libgeda/src/o_text_basic.c | 49 +++++++---- libgeda/src/scheme_page.c | 9 ++- 21 files changed, 408 insertions(+), 274 deletions(-) diff --git a/gnetlist/src/gnetlist.c b/gnetlist/src/gnetlist.c index 4d7120c..d674bfb 100644 --- a/gnetlist/src/gnetlist.c +++ b/gnetlist/src/gnetlist.c @@ -232,6 +232,7 @@ void main_prog(void *closure, int argc, char *argv[]) g_warning ("%s\n", err->message); fprintf (stderr, "%s\n", err->message); g_error_free (err); + exit(2); } /* collect input filenames for backend use */ diff --git a/gschem/src/o_complex.c b/gschem/src/o_complex.c index 05e4cb3..b74d143 100644 --- a/gschem/src/o_complex.c +++ b/gschem/src/o_complex.c @@ -71,6 +71,7 @@ void o_complex_prepare_place(GSCHEM_TOPLEVEL *w_current, const CLibSymbol *sym) OBJECT *o_current; char *buffer; const gchar *sym_name = s_clib_symbol_get_name (sym); + GError *err = NULL; /* remove the old place list if it exists */ s_delete_object_glist(toplevel, toplevel->page_current->place_list); @@ -90,7 +91,11 @@ void o_complex_prepare_place(GSCHEM_TOPLEVEL *w_current, const CLibSymbol *sym) temp_list = o_read_buffer (toplevel, temp_list, buffer, -1, - sym_name); + sym_name, + &err); + // FIXME: How can we improve the error handling here? Currently err is ignored. + if (err) + g_error_free(err); g_free (buffer); /* Take the added objects */ diff --git a/gschem/src/x_clipboard.c b/gschem/src/x_clipboard.c index d89018c..48a8c76 100644 --- a/gschem/src/x_clipboard.c +++ b/gschem/src/x_clipboard.c @@ -224,6 +224,7 @@ x_clipboard_get (GSCHEM_TOPLEVEL *w_current) GtkSelectionData *selection_data; GList *object_list = NULL; const guchar *buf; + GError * err = NULL; /* Try to get the contents of the clipboard */ selection_data = gtk_clipboard_wait_for_contents (cb, type); @@ -237,8 +238,15 @@ x_clipboard_get (GSCHEM_TOPLEVEL *w_current) #endif object_list = o_read_buffer (toplevel, object_list, - (gchar *) buf, -1, "Clipboard"); + (gchar *) buf, -1, "Clipboard", &err); + if (err) { + char * msg = g_strdup_printf(_("Invalid schematic on clipboard: %s"), err->message); + + generic_msg_dialog(msg); + g_free(msg); + g_error_free(err); + } gtk_selection_data_free (selection_data); return object_list; } diff --git a/gschem/src/x_preview.c b/gschem/src/x_preview.c index be76d64..810366b 100644 --- a/gschem/src/x_preview.c +++ b/gschem/src/x_preview.c @@ -204,6 +204,7 @@ preview_update (Preview *preview) TOPLEVEL *preview_toplevel = preview_w_current->toplevel; int left, top, right, bottom; int width, height; + GError * err = NULL; if (preview_toplevel->page_current == NULL) { return; @@ -230,7 +231,14 @@ preview_update (Preview *preview) s_page_append_list (preview_toplevel, preview_toplevel->page_current, o_read_buffer (preview_toplevel, NULL, preview->buffer, -1, - _("Preview Buffer"))); + _("Preview Buffer"), &err)); + if (err) { + char * msg = g_strdup_printf(_("Invalid schematic: %s"), err->message); + + generic_msg_dialog(msg); + g_free(msg); + g_error_free(err); + } } } diff --git a/libgeda/include/libgeda/edaerrors.h b/libgeda/include/libgeda/edaerrors.h index cda48ae..c60d2ae 100644 --- a/libgeda/include/libgeda/edaerrors.h +++ b/libgeda/include/libgeda/edaerrors.h @@ -25,6 +25,7 @@ typedef enum { EDA_ERROR_SCHEME, /* A Scheme error occurred */ EDA_ERROR_RC_TWICE, /* Attempted to read a configuration file twice */ EDA_ERROR_NUM_ERRORS, + EDA_ERROR_READ, } EdaError; GQuark eda_error_quark (void); diff --git a/libgeda/include/libgeda/prototype.h b/libgeda/include/libgeda/prototype.h index e531835..58cbb2b 100644 --- a/libgeda/include/libgeda/prototype.h +++ b/libgeda/include/libgeda/prototype.h @@ -3,7 +3,7 @@ const gchar *o_file_format_header(); gchar *o_save_buffer (TOPLEVEL *toplevel, const GList *object_list); int o_save (TOPLEVEL *toplevel, const GList *object_list, const char *filename, GError **err); -GList *o_read_buffer(TOPLEVEL *toplevel, GList *object_list, char *buffer, const int size, const char *name); +GList *o_read_buffer(TOPLEVEL *toplevel, GList *object_list, char *buffer, const int size, const char *name, GError **err); GList *o_read(TOPLEVEL *toplevel, GList *object_list, char *filename, GError **err); void o_scale(TOPLEVEL *toplevel, GList *list, int x_scale, int y_scale); diff --git a/libgeda/include/prototype_priv.h b/libgeda/include/prototype_priv.h index bc8b403..2ef8363 100644 --- a/libgeda/include/prototype_priv.h +++ b/libgeda/include/prototype_priv.h @@ -71,7 +71,7 @@ void m_transform_scale(TRANSFORM *transform, gdouble factor); void m_transform_translate(TRANSFORM *transform, gdouble dx, gdouble dy); /* o_arc_basic.c */ -OBJECT *o_arc_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver); +OBJECT *o_arc_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver, GError **err); char *o_arc_save(TOPLEVEL *toplevel, OBJECT *object); void o_arc_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current, int origin_x, int origin_y); void o_arc_print_solid(TOPLEVEL *toplevel, FILE *fp, int x, int y, int radius, int angle1, int angle2, int color, int arc_width, int length, int space, int origin_x, int origin_y); @@ -87,11 +87,10 @@ void o_arc_recalc(TOPLEVEL *toplevel, OBJECT *o_current); /* o_attrib.c */ GList *o_read_attribs(TOPLEVEL *toplevel, - GList *list, OBJECT *object_to_get_attribs, TextBuffer *tb, unsigned int release_ver, - unsigned int fileformat_ver); + unsigned int fileformat_ver, GError **err); OBJECT *o_attrib_find_attrib_by_name(const GList *list, char *name, int count); /* o_basic.c */ @@ -102,7 +101,7 @@ void o_emit_pre_change_notify(TOPLEVEL *toplevel, OBJECT *object); void o_emit_change_notify(TOPLEVEL *toplevel, OBJECT *object); /* o_box_basic.c */ -OBJECT *o_box_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver); +OBJECT *o_box_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver, GError **err); char *o_box_save(TOPLEVEL *toplevel, OBJECT *object); void o_box_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current, int origin_x, int origin_y); void o_box_print_solid(TOPLEVEL *toplevel, FILE *fp, int x, int y, int width, int height, int color, int line_width, int length, int space, int origin_x, int origin_y); @@ -119,7 +118,7 @@ gboolean o_box_get_position(TOPLEVEL *toplevel, gint *x, gint *y, OBJECT *object void o_box_recalc(TOPLEVEL *toplevel, OBJECT *o_current); /* o_bus_basic.c */ -OBJECT *o_bus_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver); +OBJECT *o_bus_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver, GError **err); char *o_bus_save(TOPLEVEL *toplevel, OBJECT *object); void o_bus_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current, int origin_x, int origin_y); void world_get_bus_bounds(TOPLEVEL *toplevel, OBJECT *object, int *left, int *top, int *right, int *bottom); @@ -127,7 +126,7 @@ gboolean o_bus_get_position(TOPLEVEL *toplevel, gint *x, gint *y, OBJECT *object void o_bus_recalc(TOPLEVEL *toplevel, OBJECT *o_current); /* o_circle_basic.c */ -OBJECT *o_circle_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver); +OBJECT *o_circle_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver, GError **err); char *o_circle_save(TOPLEVEL *toplevel, OBJECT *object); void o_circle_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current, int origin_x, int origin_y); void o_circle_print_solid(TOPLEVEL *toplevel, FILE *fp, int x, int y, int radius, int color, int circle_width, int length, int space, int origin_x, int origin_y); @@ -144,7 +143,7 @@ gboolean o_circle_get_position(TOPLEVEL *toplevel, gint *x, gint *y, OBJECT *obj void o_circle_recalc(TOPLEVEL *toplevel, OBJECT *o_current); /* o_complex_basic.c */ -OBJECT *o_complex_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver); +OBJECT *o_complex_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver, GError **err); char *o_complex_save(TOPLEVEL *toplevel, OBJECT *object); double o_complex_shortest_distance(OBJECT *object, int x, int y, int force_soild); void world_get_complex_bounds(TOPLEVEL *toplevel, OBJECT *complex, int *left, int *top, int *right, int *bottom); @@ -153,7 +152,7 @@ void o_complex_recalc(TOPLEVEL *toplevel, OBJECT *o_current); GList *o_complex_get_promotable (TOPLEVEL *toplevel, OBJECT *object, int detach); /* o_line_basic.c */ -OBJECT *o_line_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver); +OBJECT *o_line_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver, GError **err); char *o_line_save(TOPLEVEL *toplevel, OBJECT *object); void o_line_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current, int origin_x, int origin_y); void o_line_print_solid(TOPLEVEL *toplevel, FILE *fp, int x1, int y1, int x2, int y2, int color, int line_width, int length, int space, int origin_x, int origin_y); @@ -167,7 +166,7 @@ gboolean o_line_get_position(TOPLEVEL *toplevel, gint *x, gint *y, OBJECT *objec void o_line_recalc(TOPLEVEL *toplevel, OBJECT *o_current); /* o_net_basic.c */ -OBJECT *o_net_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver); +OBJECT *o_net_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver, GError **err); char *o_net_save(TOPLEVEL *toplevel, OBJECT *object); void o_net_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current, int origin_x, int origin_y); void world_get_net_bounds(TOPLEVEL *toplevel, OBJECT *object, int *left, int *top, int *right, int *bottom); @@ -175,7 +174,7 @@ gboolean o_net_get_position(TOPLEVEL *toplevel, gint *x, gint *y, OBJECT *object void o_net_recalc(TOPLEVEL *toplevel, OBJECT *o_current); /* o_path_basic.c */ -OBJECT *o_path_read(TOPLEVEL *toplevel, const char *first_line, TextBuffer *tb, unsigned int release_ver, unsigned int fileformat_ver); +OBJECT *o_path_read(TOPLEVEL *toplevel, const char *first_line, TextBuffer *tb, unsigned int release_ver, unsigned int fileformat_ver, GError **err); char *o_path_save(TOPLEVEL *toplevel, OBJECT *object); void o_path_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current, int origin_x, int origin_y); double o_path_shortest_distance(OBJECT *object, int x, int y, int force_soild); @@ -185,7 +184,7 @@ void o_path_recalc(TOPLEVEL *toplevel, OBJECT *o_current); /* o_picture.c */ -OBJECT *o_picture_read(TOPLEVEL *toplevel, const char *first_line, TextBuffer *tb, unsigned int release_ver, unsigned int fileformat_ver); +OBJECT *o_picture_read(TOPLEVEL *toplevel, const char *first_line, TextBuffer *tb, unsigned int release_ver, unsigned int fileformat_ver, GError **err); char *o_picture_save(TOPLEVEL *toplevel, OBJECT *object); void o_picture_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current, int origin_x, int origin_y); @@ -195,7 +194,7 @@ gboolean o_picture_get_position(TOPLEVEL *toplevel, gint *x, gint *y, OBJECT *ob void o_picture_recalc(TOPLEVEL *toplevel, OBJECT *o_current); /* o_pin_basic.c */ -OBJECT *o_pin_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver); +OBJECT *o_pin_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver, GError **err); char *o_pin_save(TOPLEVEL *toplevel, OBJECT *object); void o_pin_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current, int origin_x, int origin_y); void world_get_pin_bounds(TOPLEVEL *toplevel, OBJECT *object, int *left, int *top, int *right, int *bottom); @@ -203,7 +202,7 @@ gboolean o_pin_get_position(TOPLEVEL *toplevel, gint *x, gint *y, OBJECT *object void o_pin_recalc(TOPLEVEL *toplevel, OBJECT *o_current); /* o_text_basic.c */ -OBJECT *o_text_read(TOPLEVEL *toplevel, const char *first_line, TextBuffer *tb, unsigned int release_ver, unsigned int fileformat_ver); +OBJECT *o_text_read(TOPLEVEL *toplevel, const char *first_line, TextBuffer *tb, unsigned int release_ver, unsigned int fileformat_ver, GError **err); char *o_text_save(TOPLEVEL *toplevel, OBJECT *object); void o_text_print_text_string(FILE *fp, char *string, int unicode_count, gunichar *unicode_table); void o_text_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current, int origin_x, int origin_y, int unicode_count, gunichar *unicode_table); diff --git a/libgeda/src/a_basic.c b/libgeda/src/a_basic.c index 9be1f1b..aedbba9 100644 --- a/libgeda/src/a_basic.c +++ b/libgeda/src/a_basic.c @@ -268,7 +268,7 @@ int o_save (TOPLEVEL *toplevel, const GList *object_list, */ GList *o_read_buffer (TOPLEVEL *toplevel, GList *object_list, char *buffer, const int size, - const char *name) + const char *name, GError **err) { char *line = NULL; TextBuffer *tb = NULL; @@ -276,7 +276,8 @@ GList *o_read_buffer (TOPLEVEL *toplevel, GList *object_list, char objtype; GList *object_list_save=NULL; OBJECT *new_obj=NULL; - GList *new_obj_list; + GList *new_attrs_list; + GList *new_object_list = NULL; GList *iter; unsigned int release_ver; unsigned int fileformat_ver; @@ -295,8 +296,6 @@ GList *o_read_buffer (TOPLEVEL *toplevel, GList *object_list, tb = s_textbuffer_new (buffer, size); - object_list = g_list_reverse (object_list); - while (1) { line = s_textbuffer_next_line(tb); @@ -321,42 +320,50 @@ GList *o_read_buffer (TOPLEVEL *toplevel, GList *object_list, switch (objtype) { case(OBJ_LINE): - new_obj = o_line_read (toplevel, line, release_ver, fileformat_ver); - object_list = g_list_prepend (object_list, new_obj); + if ((new_obj = o_line_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL) + goto error; + new_object_list = g_list_prepend (new_object_list, new_obj); break; case(OBJ_NET): - new_obj = o_net_read (toplevel, line, release_ver, fileformat_ver); - object_list = g_list_prepend (object_list, new_obj); + if ((new_obj = o_net_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL) + goto error; + new_object_list = g_list_prepend (new_object_list, new_obj); break; case(OBJ_BUS): - new_obj = o_bus_read (toplevel, line, release_ver, fileformat_ver); - object_list = g_list_prepend (object_list, new_obj); + if ((new_obj = o_bus_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL) + goto error; + new_object_list = g_list_prepend (new_object_list, new_obj); break; case(OBJ_BOX): - new_obj = o_box_read (toplevel, line, release_ver, fileformat_ver); - object_list = g_list_prepend (object_list, new_obj); + if ((new_obj = o_box_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL) + goto error; + new_object_list = g_list_prepend (new_object_list, new_obj); break; case(OBJ_PICTURE): line = g_strdup (line); - new_obj = o_picture_read (toplevel, line, tb, release_ver, fileformat_ver); + new_obj = o_picture_read (toplevel, line, tb, release_ver, fileformat_ver, err); g_free (line); - object_list = g_list_prepend (object_list, new_obj); + if (new_obj == NULL) + goto error; + new_object_list = g_list_prepend (new_object_list, new_obj); break; case(OBJ_CIRCLE): - new_obj = o_circle_read (toplevel, line, release_ver, fileformat_ver); - object_list = g_list_prepend (object_list, new_obj); + if ((new_obj = o_circle_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL) + goto error; + new_object_list = g_list_prepend (new_object_list, new_obj); break; case(OBJ_COMPLEX): case(OBJ_PLACEHOLDER): - new_obj = o_complex_read (toplevel, line, release_ver, fileformat_ver); - object_list = g_list_prepend (object_list, new_obj); + if ((new_obj = o_complex_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL) + goto error; + new_object_list = g_list_prepend (new_object_list, new_obj); /* last_complex is used for verifying symversion attribute */ last_complex = new_obj; @@ -364,71 +371,86 @@ GList *o_read_buffer (TOPLEVEL *toplevel, GList *object_list, case(OBJ_TEXT): line = g_strdup (line); - new_obj = o_text_read (toplevel, line, tb, release_ver, fileformat_ver); + new_obj = o_text_read (toplevel, line, tb, release_ver, fileformat_ver, err); g_free (line); - object_list = g_list_prepend (object_list, new_obj); + if (new_obj == NULL) + goto error; + new_object_list = g_list_prepend (new_object_list, new_obj); break; case(OBJ_PATH): line = g_strdup(line); - new_obj = o_path_read (toplevel, line, tb, release_ver, fileformat_ver); + new_obj = o_path_read (toplevel, line, tb, release_ver, fileformat_ver, err); g_free (line); - object_list = g_list_prepend (object_list, new_obj); + if (new_obj == NULL) + goto error; + new_object_list = g_list_prepend (new_object_list, new_obj); break; case(OBJ_PIN): - new_obj = o_pin_read (toplevel, line, release_ver, fileformat_ver); - object_list = g_list_prepend (object_list, new_obj); + if ((new_obj = o_pin_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL) + goto error; + new_object_list = g_list_prepend (new_object_list, new_obj); found_pin++; break; case(OBJ_ARC): - new_obj = o_arc_read (toplevel, line, release_ver, fileformat_ver); - object_list = g_list_prepend (object_list, new_obj); + if ((new_obj = o_arc_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL) + goto error; + new_object_list = g_list_prepend (new_object_list, new_obj); break; case(STARTATTACH_ATTR): /* first is the fp */ /* 2nd is the object to get the attributes */ - new_obj_list = o_read_attribs (toplevel, NULL, new_obj, tb, release_ver, fileformat_ver); - new_obj_list = g_list_reverse (new_obj_list); - object_list = g_list_concat (new_obj_list, object_list); - - /* by now we have finished reading all the attributes */ - /* did we just finish attaching to a complex object? */ - if (last_complex) - { - /* yes */ - /* verify symbol version (not file format but rather contents) */ - o_complex_check_symversion(toplevel, last_complex); - last_complex = NULL; - } + if (new_obj != NULL) { + new_attrs_list = o_read_attribs (toplevel, new_obj, tb, release_ver, fileformat_ver, err); + if (new_attrs_list == NULL) + goto error; + new_object_list = g_list_concat (new_object_list, new_attrs_list); + + /* by now we have finished reading all the attributes */ + /* did we just finish attaching to a complex object? */ + if (last_complex) + { + /* yes */ + /* verify symbol version (not file format but rather contents) */ + o_complex_check_symversion(toplevel, last_complex); + last_complex = NULL; + } - /* slots only apply to complex objects */ - if (new_obj != NULL && - (new_obj->type == OBJ_COMPLEX || - new_obj->type == OBJ_PLACEHOLDER)) { - s_slot_update_object (toplevel, new_obj); + /* slots only apply to complex objects */ + if (new_obj != NULL && + (new_obj->type == OBJ_COMPLEX || + new_obj->type == OBJ_PLACEHOLDER)) { + s_slot_update_object (toplevel, new_obj); + } + new_obj = NULL; + } + else { + g_set_error (err, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Read unexpected attach " + "symbol start marker in [%s] :\n>>\n%s<<\n"), + name, line); + goto error; } - - new_obj = NULL; break; case(START_EMBEDDED): - new_obj = object_list->data; + new_obj = new_object_list->data; if (new_obj != NULL && (new_obj->type == OBJ_COMPLEX || new_obj->type == OBJ_PLACEHOLDER)) { - object_list_save = object_list; - object_list = new_obj->complex->prim_objs; + object_list_save = new_object_list; + new_object_list = new_obj->complex->prim_objs; embedded_level++; } else { - fprintf(stderr, _("Read unexpected embedded " - "symbol start marker in [%s] :\n>>\n%s<<\n"), - name, line); + g_set_error (err, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Read unexpected embedded " + "symbol start marker in [%s] :\n>>\n%s<<\n"), + name, line); + goto error; } break; @@ -436,14 +458,14 @@ GList *o_read_buffer (TOPLEVEL *toplevel, GList *object_list, if (embedded_level>0) { /* don't do this since objects are already * stored/read translated - * o_complex_translate_world (toplevel, object_list->x, - * object_list->y, object_list->complex); + * o_complex_translate_world (toplevel, new_object_list->x, + * new_object_list->y, new_object_list->complex); */ - object_list = g_list_reverse (object_list); + new_object_list = g_list_reverse (new_object_list); new_obj = object_list_save->data; - new_obj->complex->prim_objs = object_list; - object_list = object_list_save; + new_obj->complex->prim_objs = new_object_list; + new_object_list = object_list_save; /* set the parent field now */ for (iter = new_obj->complex->prim_objs; @@ -456,9 +478,10 @@ GList *o_read_buffer (TOPLEVEL *toplevel, GList *object_list, embedded_level--; } else { - fprintf(stderr, _("Read unexpected embedded " - "symbol end marker in [%s] :\n>>\n%s<<\n"), - name, line); + g_set_error (err, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Read unexpected embedded " + "symbol end marker in [%s] :\n>>\n%s<<\n"), + name, line); + goto error; } break; @@ -477,6 +500,11 @@ GList *o_read_buffer (TOPLEVEL *toplevel, GList *object_list, case(VERSION_CHAR): itemsread = sscanf(line, "v %u %u\n", &release_ver, &fileformat_ver); + if (itemsread == 0) { + g_set_error (err, G_FILE_ERROR, G_FILE_ERROR_FAILED, "Failed to parse version from buffer.\n"); + goto error; + } + /* 20030921 was the last version which did not have a fileformat */ /* version. The below latter test should not happen, but it is here */ /* just in in case. */ @@ -491,10 +519,9 @@ GList *o_read_buffer (TOPLEVEL *toplevel, GList *object_list, break; default: - fprintf(stderr, _("Read garbage in [%s] :\n>>\n%s<<\n"), - name, line); + g_set_error (err, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Read garbage in [%s] :\n>>\n%s<<\n"), name, line); new_obj = NULL; - break; + goto error; } } @@ -510,16 +537,19 @@ GList *o_read_buffer (TOPLEVEL *toplevel, GList *object_list, if (found_pin) { if (release_ver <= VERSION_20020825) { - o_pin_update_whichend (toplevel, object_list, found_pin); + o_pin_update_whichend (toplevel, new_object_list, found_pin); } } tb = s_textbuffer_free(tb); - object_list = g_list_reverse (object_list); + new_object_list = g_list_reverse(new_object_list); + object_list = g_list_concat (object_list, new_object_list); return(object_list); - + error: + s_delete_object_glist(toplevel, new_object_list); + return NULL; } /*! \brief Read a file @@ -549,7 +579,7 @@ GList *o_read (TOPLEVEL *toplevel, GList *object_list, char *filename, } /* Parse file contents */ - result = o_read_buffer (toplevel, object_list, buffer, size, filename); + result = o_read_buffer (toplevel, object_list, buffer, size, filename, err); g_free (buffer); return result; } diff --git a/libgeda/src/o_arc_basic.c b/libgeda/src/o_arc_basic.c index 39b0e8f..37cff66 100644 --- a/libgeda/src/o_arc_basic.c +++ b/libgeda/src/o_arc_basic.c @@ -230,10 +230,10 @@ void o_arc_modify(TOPLEVEL *toplevel, OBJECT *object, * \param [in] buf * \param [in] release_ver * \param [in] fileformat_ver - * \return + * \return The ARC OBJECT that was created, or NULL on error. */ OBJECT *o_arc_read (TOPLEVEL *toplevel, char buf[], - unsigned int release_ver, unsigned int fileformat_ver) + unsigned int release_ver, unsigned int fileformat_ver, GError **err) { OBJECT *new_obj; char type; @@ -251,8 +251,11 @@ OBJECT *o_arc_read (TOPLEVEL *toplevel, char buf[], * restrictive - the oldest - file format are set to common values */ if(release_ver <= VERSION_20000704) { - sscanf(buf, "%c %d %d %d %d %d %d", &type, - &x1, &y1, &radius, &start_angle, &end_angle, &color); + if (sscanf(buf, "%c %d %d %d %d %d %d", &type, + &x1, &y1, &radius, &start_angle, &end_angle, &color) != 7) { + g_set_error (err, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Failed to parse arc object\n")); + return NULL; + } arc_width = 0; arc_end = END_NONE; @@ -260,16 +263,19 @@ OBJECT *o_arc_read (TOPLEVEL *toplevel, char buf[], arc_space = -1; arc_length= -1; } else { - sscanf(buf, "%c %d %d %d %d %d %d %d %d %d %d %d", &type, - &x1, &y1, &radius, &start_angle, &end_angle, &color, - &arc_width, &arc_end, &arc_type, &arc_length, &arc_space); - + if (sscanf(buf, "%c %d %d %d %d %d %d %d %d %d %d %d", &type, + &x1, &y1, &radius, &start_angle, &end_angle, &color, + &arc_width, &arc_end, &arc_type, &arc_length, &arc_space) != 12) { + g_set_error (err, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Failed to parse arc object\n")); + return NULL; + } } /* Error check */ if (radius <= 0) { s_log_message (_("Found a zero radius arc [ %c %d, %d, %d, %d, %d, %d ]\n"), type, x1, y1, radius, start_angle, end_angle, color); + radius = 0; } if (color < 0 || color > MAX_COLORS) { diff --git a/libgeda/src/o_attrib.c b/libgeda/src/o_attrib.c index cd2cb19..93da42c 100644 --- a/libgeda/src/o_attrib.c +++ b/libgeda/src/o_attrib.c @@ -226,27 +226,23 @@ void o_attrib_remove(TOPLEVEL *toplevel, GList **list, OBJECT *remove) * Read attributes from a TextBuffer. * * \param [in] toplevel The TOPLEVEL object. - * \param [out] list Storage for attributes. * \param [in] object_to_get_attribs Object which gets these attribs. * \param [in] tb The text buffer to read from. * \param [in] release_ver libgeda release version number. * \param [in] fileformat_ver file format version number. - * \return GList of attributes read. + * \return GList of attributes read, or NULL on error. */ GList *o_read_attribs (TOPLEVEL *toplevel, - GList *list, OBJECT *object_to_get_attribs, TextBuffer *tb, - unsigned int release_ver, unsigned int fileformat_ver) + unsigned int release_ver, unsigned int fileformat_ver, GError ** err) { - GList *object_list; + GList *object_list = NULL; OBJECT *new_obj; char *line = NULL; char objtype; int ATTACH=FALSE; - object_list = g_list_reverse (list); - while (1) { line = s_textbuffer_next_line (tb); @@ -256,66 +252,78 @@ GList *o_read_attribs (TOPLEVEL *toplevel, switch (objtype) { case(OBJ_LINE): - new_obj = o_line_read (toplevel, line, release_ver, fileformat_ver); + if ((new_obj = o_line_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL) + goto error; object_list = g_list_prepend (object_list, new_obj); break; case(OBJ_NET): - new_obj = o_net_read (toplevel, line, release_ver, fileformat_ver); + if ((new_obj = o_net_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL) + goto error; object_list = g_list_prepend (object_list, new_obj); break; case(OBJ_BUS): - new_obj = o_bus_read (toplevel, line, release_ver, fileformat_ver); + if ((new_obj = o_bus_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL) + goto error; object_list = g_list_prepend (object_list, new_obj); break; case(OBJ_BOX): - new_obj = o_box_read (toplevel, line, release_ver, fileformat_ver); + if ((new_obj = o_box_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL) + goto error; object_list = g_list_prepend (object_list, new_obj); break; case(OBJ_CIRCLE): - new_obj = o_circle_read (toplevel, line, release_ver, fileformat_ver); + if ((new_obj = o_circle_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL) + goto error; object_list = g_list_prepend (object_list, new_obj); break; case(OBJ_COMPLEX): case(OBJ_PLACEHOLDER): - new_obj = o_complex_read (toplevel, line, release_ver, fileformat_ver); + if ((new_obj = o_complex_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL) + goto error; object_list = g_list_prepend (object_list, new_obj); break; case(OBJ_PATH): line = g_strdup (line); - new_obj = o_path_read (toplevel, line, tb, release_ver, fileformat_ver); + new_obj = o_path_read (toplevel, line, tb, release_ver, fileformat_ver, err); g_free (line); + if (new_obj == NULL) + goto error; object_list = g_list_prepend (object_list, new_obj); break; case(OBJ_PIN): - new_obj = o_pin_read (toplevel, line, release_ver, fileformat_ver); + if ((new_obj = o_pin_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL) + goto error; object_list = g_list_prepend (object_list, new_obj); break; case(OBJ_ARC): - new_obj = o_arc_read (toplevel, line, release_ver, fileformat_ver); + if ((new_obj = o_arc_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL) + goto error; object_list = g_list_prepend (object_list, new_obj); break; case(OBJ_TEXT): line = g_strdup (line); - new_obj = o_text_read (toplevel, line, tb, release_ver, fileformat_ver); + new_obj = o_text_read (toplevel, line, tb, release_ver, fileformat_ver, err); g_free (line); + if (new_obj == NULL) + goto error; object_list = g_list_prepend (object_list, new_obj); ATTACH=TRUE; break; - case(ENDATTACH_ATTR): + case(ENDATTACH_ATTR): object_list = g_list_reverse (object_list); - return(object_list); + return object_list; break; } @@ -324,11 +332,17 @@ GList *o_read_attribs (TOPLEVEL *toplevel, o_attrib_attach (toplevel, new_obj, object_to_get_attribs, FALSE); ATTACH=FALSE; } else { - fprintf(stderr, "Tried to attach a non-text item as an attribute\n"); + g_set_error(err, EDA_ERROR, EDA_ERROR_READ, _("Tried to attach a non-text item as an attribute\n")); + goto error; } } object_list = g_list_reverse (object_list); + return(object_list); + +error: + s_delete_object_glist(toplevel, object_list); + return NULL; } diff --git a/libgeda/src/o_box_basic.c b/libgeda/src/o_box_basic.c index 8a0d165..4198205 100644 --- a/libgeda/src/o_box_basic.c +++ b/libgeda/src/o_box_basic.c @@ -254,10 +254,10 @@ void o_box_modify(TOPLEVEL *toplevel, OBJECT *object, * \param [in] buf Character string with box description. * \param [in] release_ver libgeda release version number. * \param [in] fileformat_ver libgeda file format version number. - * \return The BOX OBJECT that was created. + * \return The BOX OBJECT that was created, or NULL on error. */ OBJECT *o_box_read (TOPLEVEL *toplevel, char buf[], - unsigned int release_ver, unsigned int fileformat_ver) + unsigned int release_ver, unsigned int fileformat_ver, GError **err) { OBJECT *new_obj; char type; @@ -280,8 +280,11 @@ OBJECT *o_box_read (TOPLEVEL *toplevel, char buf[], * to default. */ - sscanf (buf, "%c %d %d %d %d %d\n", - &type, &x1, &y1, &width, &height, &color); + if (sscanf (buf, "%c %d %d %d %d %d\n", + &type, &x1, &y1, &width, &height, &color) != 6) { + g_set_error(err, EDA_ERROR, EDA_ERROR_READ, _("Failed to parse box object\n")); + return NULL; + } box_width = 0; box_end = END_NONE; @@ -303,11 +306,14 @@ OBJECT *o_box_read (TOPLEVEL *toplevel, char buf[], * characters and numbers in plain ASCII on a single line. The meaning of * each item is described in the file format documentation. */ - sscanf (buf, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", - &type, &x1, &y1, &width, &height, &color, - &box_width, &box_end, &box_type, &box_length, - &box_space, &box_filling, - &fill_width, &angle1, &pitch1, &angle2, &pitch2); + if (sscanf (buf, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", + &type, &x1, &y1, &width, &height, &color, + &box_width, &box_end, &box_type, &box_length, + &box_space, &box_filling, + &fill_width, &angle1, &pitch1, &angle2, &pitch2) != 17) { + g_set_error(err, EDA_ERROR, EDA_ERROR_READ, _("Failed to parse box object\n")); + return NULL; + } } if (width == 0 || height == 0) { diff --git a/libgeda/src/o_bus_basic.c b/libgeda/src/o_bus_basic.c index ae22db7..0cefe04 100644 --- a/libgeda/src/o_bus_basic.c +++ b/libgeda/src/o_bus_basic.c @@ -143,10 +143,10 @@ void o_bus_recalc(TOPLEVEL *toplevel, OBJECT *o_current) * \param [in] buf a text buffer (usually a line of a schematic file) * \param [in] release_ver The release number gEDA * \param [in] fileformat_ver a integer value of the file format - * \return The object list + * \return The object list, or NULL on error. */ OBJECT *o_bus_read (TOPLEVEL *toplevel, char buf[], - unsigned int release_ver, unsigned int fileformat_ver) + unsigned int release_ver, unsigned int fileformat_ver, GError **err) { OBJECT *new_obj; char type; @@ -156,11 +156,17 @@ OBJECT *o_bus_read (TOPLEVEL *toplevel, char buf[], int ripper_dir; if (release_ver <= VERSION_20020825) { - sscanf (buf, "%c %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color); + if (sscanf (buf, "%c %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color) != 6) { + g_set_error(err, EDA_ERROR, EDA_ERROR_READ, _("Failed to parse bus object\n")); + return NULL; + } ripper_dir = 0; } else { - sscanf (buf, "%c %d %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color, - &ripper_dir); + if (sscanf (buf, "%c %d %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color, + &ripper_dir) != 7) { + g_set_error(err, EDA_ERROR, EDA_ERROR_READ, _("Failed to parse bus object\n")); + return NULL; + } } if (x1 == x2 && y1 == y2) { diff --git a/libgeda/src/o_circle_basic.c b/libgeda/src/o_circle_basic.c index 92c839a..da43b73 100644 --- a/libgeda/src/o_circle_basic.c +++ b/libgeda/src/o_circle_basic.c @@ -220,10 +220,10 @@ void o_circle_modify(TOPLEVEL *toplevel, OBJECT *object, * \param [in] buf Character string with circle description. * \param [in] release_ver libgeda release version number. * \param [in] fileformat_ver libgeda file format version number. - * \return A pointer to the new circle object. + * \return A pointer to the new circle object, or NULL on error. */ OBJECT *o_circle_read (TOPLEVEL *toplevel, char buf[], - unsigned int release_ver, unsigned int fileformat_ver) + unsigned int release_ver, unsigned int fileformat_ver, GError ** err) { OBJECT *new_obj; char type; @@ -242,7 +242,10 @@ OBJECT *o_circle_read (TOPLEVEL *toplevel, char buf[], * handle the line type and the filling of the box object. They are set * to default. */ - sscanf(buf, "%c %d %d %d %d\n", &type, &x1, &y1, &radius, &color); + if (sscanf(buf, "%c %d %d %d %d\n", &type, &x1, &y1, &radius, &color) != 5) { + g_set_error(err, EDA_ERROR, EDA_ERROR_READ, _("Failed to parse circle object\n")); + return NULL; + } circle_width = 0; circle_end = END_NONE; @@ -264,18 +267,22 @@ OBJECT *o_circle_read (TOPLEVEL *toplevel, char buf[], * list of characters and numbers in plain ASCII on a single line. The * meaning of each item is described in the file format documentation. */ - sscanf(buf, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", - &type, &x1, &y1, &radius, &color, - &circle_width, &circle_end, &circle_type, - &circle_length, &circle_space, &circle_fill, - &fill_width, &angle1, &pitch1, &angle2, &pitch2); + if (sscanf(buf, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", + &type, &x1, &y1, &radius, &color, + &circle_width, &circle_end, &circle_type, + &circle_length, &circle_space, &circle_fill, + &fill_width, &angle1, &pitch1, &angle2, &pitch2) != 16) { + g_set_error(err, EDA_ERROR, EDA_ERROR_READ, _("Failed to parse circle object\n")); + return NULL; + } } - if (radius == 0) { - s_log_message(_("Found a zero radius circle [ %c %d %d %d %d ]\n"), + if (radius <= 0) { + s_log_message(_("Found a zero or negative radius circle [ %c %d %d %d %d ]\n"), type, x1, y1, radius, color); - + s_log_message (_("Setting radius to 0\n")); + radius = 0; } if (color < 0 || color > MAX_COLORS) { diff --git a/libgeda/src/o_complex_basic.c b/libgeda/src/o_complex_basic.c index 48c79c5..59eab03 100644 --- a/libgeda/src/o_complex_basic.c +++ b/libgeda/src/o_complex_basic.c @@ -392,62 +392,13 @@ static void o_complex_remove_promotable_attribs (TOPLEVEL *toplevel, OBJECT *obj g_list_free (promotable); } - -/* Done */ -/*! \brief - * \par Function Description - * - */ -OBJECT *o_complex_new(TOPLEVEL *toplevel, - char type, - int color, int x, int y, int angle, - int mirror, const CLibSymbol *clib, - const gchar *basename, - int selectable) +static void create_placeholder(TOPLEVEL * toplevel, OBJECT * new_node, int x, int y) { - OBJECT *new_node=NULL; - OBJECT *new_prim_obj; - GList *prim_objs; - GList *iter; - int loaded_normally = FALSE; - - gchar *buffer = NULL; - - new_node = s_basic_new_object(type, "complex"); - - if (clib != NULL) { - new_node->complex_basename = g_strdup (s_clib_symbol_get_name (clib)); - } else { - new_node->complex_basename = g_strdup (basename); - } - - - new_node->complex_embedded = FALSE; - new_node->color = color; - new_node->selectable = selectable; - - new_node->complex = (COMPLEX *) g_malloc(sizeof(COMPLEX)); - new_node->complex->angle = angle; - new_node->complex->mirror = mirror; - new_node->complex->x = x; - new_node->complex->y = y; - - prim_objs = NULL; - - /* get the symbol data */ - if (clib != NULL) { - buffer = s_clib_symbol_get_data (clib); - } - - if (clib == NULL || buffer == NULL) { - + OBJECT *new_prim_obj; char *not_found_text = NULL; int left, right, top, bottom; int x_offset, y_offset; - /* filename was NOT found */ - loaded_normally = FALSE; - /* Put placeholder into object list. Changed by SDB on * 1.19.2005 to fix problem that symbols were silently * deleted by gattrib when RC files were messed up. */ @@ -457,23 +408,23 @@ OBJECT *o_complex_new(TOPLEVEL *toplevel, new_prim_obj = o_line_new(toplevel, OBJ_LINE, DETACHED_ATTRIBUTE_COLOR, x - 50, y, x + 50, y); - prim_objs = g_list_append (prim_objs, new_prim_obj); + new_node->complex->prim_objs = g_list_prepend (new_node->complex->prim_objs, new_prim_obj); new_prim_obj = o_line_new(toplevel, OBJ_LINE, DETACHED_ATTRIBUTE_COLOR, x, y + 50, x, y - 50); - prim_objs = g_list_append (prim_objs, new_prim_obj); + new_node->complex->prim_objs = g_list_prepend (new_node->complex->prim_objs, new_prim_obj); /* Add some useful text */ not_found_text = g_strdup_printf (_("Component not found:\n %s"), - new_node->complex_basename); + new_node->complex_basename); new_prim_obj = o_text_new(toplevel, OBJ_TEXT, DETACHED_ATTRIBUTE_COLOR, x + NOT_FOUND_TEXT_X, y + NOT_FOUND_TEXT_Y, LOWER_LEFT, 0, not_found_text, 8, VISIBLE, SHOW_NAME_VALUE); - prim_objs = g_list_append (prim_objs, new_prim_obj); + new_node->complex->prim_objs = g_list_prepend (new_node->complex->prim_objs, new_prim_obj); g_free(not_found_text); /* figure out where to put the hazard triangle */ @@ -490,7 +441,7 @@ OBJECT *o_complex_new(TOPLEVEL *toplevel, y + NOT_FOUND_TEXT_Y + y_offset); o_set_line_options(toplevel, new_prim_obj, END_ROUND, TYPE_SOLID, 50, -1, -1); - prim_objs = g_list_append (prim_objs, new_prim_obj); + new_node->complex->prim_objs = g_list_prepend (new_node->complex->prim_objs, new_prim_obj); new_prim_obj = o_line_new(toplevel, OBJ_LINE, DETACHED_ATTRIBUTE_COLOR, x + NOT_FOUND_TEXT_X + x_offset, @@ -499,7 +450,7 @@ OBJECT *o_complex_new(TOPLEVEL *toplevel, y + NOT_FOUND_TEXT_Y + y_offset + 500); o_set_line_options(toplevel, new_prim_obj, END_ROUND, TYPE_SOLID, 50, -1, -1); - prim_objs = g_list_append (prim_objs, new_prim_obj); + new_node->complex->prim_objs = g_list_prepend (new_node->complex->prim_objs, new_prim_obj); new_prim_obj = o_line_new(toplevel, OBJ_LINE, DETACHED_ATTRIBUTE_COLOR, x + NOT_FOUND_TEXT_X + x_offset + 300, @@ -508,43 +459,85 @@ OBJECT *o_complex_new(TOPLEVEL *toplevel, y + NOT_FOUND_TEXT_Y + y_offset); o_set_line_options(toplevel, new_prim_obj, END_ROUND, TYPE_SOLID, 50, -1, -1); - prim_objs = g_list_append (prim_objs, new_prim_obj); + new_node->complex->prim_objs = g_list_prepend (new_node->complex->prim_objs, new_prim_obj); new_prim_obj = o_text_new(toplevel, OBJ_TEXT, DETACHED_ATTRIBUTE_COLOR, x + NOT_FOUND_TEXT_X + x_offset + 270, y + NOT_FOUND_TEXT_Y + y_offset + 90, LOWER_LEFT, 0, "!", 18, VISIBLE, SHOW_NAME_VALUE); - prim_objs = g_list_append (prim_objs, new_prim_obj); + new_node->complex->prim_objs = g_list_prepend (new_node->complex->prim_objs, new_prim_obj); + new_node->complex->prim_objs = g_list_reverse(new_node->complex->prim_objs); +} + +/* Done */ +/*! \brief + * \par Function Description + * + */ +OBJECT *o_complex_new(TOPLEVEL *toplevel, + char type, + int color, int x, int y, int angle, + int mirror, const CLibSymbol *clib, + const gchar *basename, + int selectable) +{ + OBJECT *new_node=NULL; + GList *iter; + gchar *buffer = NULL; + new_node = s_basic_new_object(type, "complex"); + + if (clib != NULL) { + new_node->complex_basename = g_strdup (s_clib_symbol_get_name (clib)); } else { + new_node->complex_basename = g_strdup (basename); + } - /* filename was found */ - loaded_normally = TRUE; - /* add connections till translated */ - prim_objs = o_read_buffer (toplevel, prim_objs, buffer, -1, new_node->complex_basename); + new_node->complex_embedded = FALSE; + new_node->color = color; + new_node->selectable = selectable; - g_free (buffer); + new_node->complex = (COMPLEX *) g_malloc(sizeof(COMPLEX)); + new_node->complex->prim_objs = NULL; + new_node->complex->angle = angle; + new_node->complex->mirror = mirror; + new_node->complex->x = x; + new_node->complex->y = y; + /* get the symbol data */ + if (clib != NULL) { + buffer = s_clib_symbol_get_data (clib); } - /* do not mirror/rotate/translate/connect the primitive objects if the - * component was not loaded via o_read - */ - if (loaded_normally == TRUE) { - if (mirror) { - o_glist_mirror_world (toplevel, 0, 0, prim_objs); + if (clib == NULL || buffer == NULL) + create_placeholder(toplevel, new_node, x, y); + else { + GError * err = NULL; + + /* add connections till translated */ + new_node->complex->prim_objs = o_read_buffer (toplevel, NULL, buffer, -1, new_node->complex_basename, &err); + if (err) { + g_error_free(err); + /* If reading fails, replace with placeholder object */ + create_placeholder(toplevel, new_node, x, y); + } + else { + if (mirror) { + o_glist_mirror_world (toplevel, 0, 0, new_node->complex->prim_objs); + } + + o_glist_rotate_world (toplevel, 0, 0, angle, new_node->complex->prim_objs); + o_glist_translate_world (toplevel, x, y, new_node->complex->prim_objs); } - o_glist_rotate_world (toplevel, 0, 0, angle, prim_objs); - o_glist_translate_world (toplevel, x, y, prim_objs); - } + g_free (buffer); - new_node->complex->prim_objs = prim_objs; + } /* set the parent field now */ - for (iter = prim_objs; iter != NULL; iter = g_list_next (iter)) { + for (iter = new_node->complex->prim_objs; iter != NULL; iter = g_list_next (iter)) { OBJECT *tmp = iter->data; tmp->parent = new_node; } @@ -637,11 +630,11 @@ void o_complex_recalc(TOPLEVEL *toplevel, OBJECT *o_current) * \param [in] buf a text buffer (usually a line of a schematic file) * \param [in] release_ver The release number gEDA * \param [in] fileformat_ver a integer value of the file format - * \return The object list + * \return The object list, or NULL on error. */ OBJECT *o_complex_read (TOPLEVEL *toplevel, char buf[], unsigned int release_ver, - unsigned int fileformat_ver) + unsigned int fileformat_ver, GError **err) { OBJECT *new_obj; char type; @@ -653,8 +646,11 @@ OBJECT *o_complex_read (TOPLEVEL *toplevel, int selectable; int mirror; - sscanf(buf, "%c %d %d %d %d %d %s\n", - &type, &x1, &y1, &selectable, &angle, &mirror, basename); + if (sscanf(buf, "%c %d %d %d %d %d %s\n", + &type, &x1, &y1, &selectable, &angle, &mirror, basename) != 7) { + g_set_error(err, EDA_ERROR, EDA_ERROR_READ, _("Failed to parse complex object\n")); + return NULL; + } switch(angle) { @@ -666,7 +662,8 @@ OBJECT *o_complex_read (TOPLEVEL *toplevel, default: s_log_message(_("Found a component with an invalid rotation [ %c %d %d %d %d %d %s ]\n"), type, x1, y1, selectable, angle, mirror, basename); - break; + s_log_message (_("Setting angle to 0\n")); + angle = 0; } switch(mirror) { @@ -678,7 +675,8 @@ OBJECT *o_complex_read (TOPLEVEL *toplevel, default: s_log_message(_("Found a component with an invalid mirror flag [ %c %d %d %d %d %d %s ]\n"), type, x1, y1, selectable, angle, mirror, basename); - break; + s_log_message (_("Setting mirror to 0\n")); + mirror = 0; } if (strncmp(basename, "EMBEDDED", 8) == 0) { @@ -696,7 +694,8 @@ OBJECT *o_complex_read (TOPLEVEL *toplevel, angle, mirror, clib, basename, selectable); /* Delete or hide attributes eligible for promotion inside the complex */ - o_complex_remove_promotable_attribs (toplevel, new_obj); + if (new_obj) + o_complex_remove_promotable_attribs (toplevel, new_obj); } g_free (basename); diff --git a/libgeda/src/o_line_basic.c b/libgeda/src/o_line_basic.c index 887c525..19fb3b7 100644 --- a/libgeda/src/o_line_basic.c +++ b/libgeda/src/o_line_basic.c @@ -204,10 +204,10 @@ void o_line_modify(TOPLEVEL *toplevel, OBJECT *object, * \param [in] buf Character string with line description. * \param [in] release_ver libgeda release version number. * \param [in] fileformat_ver libgeda file format version number. - * \return A pointer to the new line object. + * \return A pointer to the new line object, or NULL on error. */ OBJECT *o_line_read (TOPLEVEL *toplevel, char buf[], - unsigned int release_ver, unsigned int fileformat_ver) + unsigned int release_ver, unsigned int fileformat_ver, GError ** err) { OBJECT *new_obj; char type; @@ -224,8 +224,11 @@ OBJECT *o_line_read (TOPLEVEL *toplevel, char buf[], * not handle the line type and the filling - here filling is irrelevant. * They are set to default. */ - sscanf (buf, "%c %d %d %d %d %d\n", &type, - &x1, &y1, &x2, &y2, &color); + if (sscanf (buf, "%c %d %d %d %d %d\n", &type, + &x1, &y1, &x2, &y2, &color) != 6) { + g_set_error(err, EDA_ERROR, EDA_ERROR_READ, _("Failed to parse line object\n")); + return NULL; + } line_width = 0; line_end = END_NONE; @@ -238,9 +241,12 @@ OBJECT *o_line_read (TOPLEVEL *toplevel, char buf[], * list of characters and numbers in plain ASCII on a single line. * The meaning of each item is described in the file format documentation. */ - sscanf (buf, "%c %d %d %d %d %d %d %d %d %d %d\n", &type, - &x1, &y1, &x2, &y2, &color, - &line_width, &line_end, &line_type, &line_length, &line_space); + if (sscanf (buf, "%c %d %d %d %d %d %d %d %d %d %d\n", &type, + &x1, &y1, &x2, &y2, &color, + &line_width, &line_end, &line_type, &line_length, &line_space) != 11) { + g_set_error(err, EDA_ERROR, EDA_ERROR_READ, _("Failed to parse line object\n")); + return NULL; + } } /* diff --git a/libgeda/src/o_net_basic.c b/libgeda/src/o_net_basic.c index 443cb4c..569a5ee 100644 --- a/libgeda/src/o_net_basic.c +++ b/libgeda/src/o_net_basic.c @@ -140,11 +140,11 @@ void o_net_recalc(TOPLEVEL *toplevel, OBJECT *o_current) * \param [in] buf a text buffer (usually a line of a schematic file) * \param [in] release_ver The release number gEDA * \param [in] fileformat_ver a integer value of the file format - * \return The object list + * \return The object list, or NULL on error. * */ OBJECT *o_net_read (TOPLEVEL *toplevel, char buf[], - unsigned int release_ver, unsigned int fileformat_ver) + unsigned int release_ver, unsigned int fileformat_ver, GError **err) { OBJECT *new_obj; char type; @@ -152,7 +152,10 @@ OBJECT *o_net_read (TOPLEVEL *toplevel, char buf[], int x2, y2; int color; - sscanf (buf, "%c %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color); + if (sscanf (buf, "%c %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color) != 6) { + g_set_error(err, EDA_ERROR, EDA_ERROR_READ, _("Failed to parse net object\n")); + return NULL; + } if (x1 == x2 && y1 == y2) { s_log_message (_("Found a zero length net [ %c %d %d %d %d %d ]\n"), diff --git a/libgeda/src/o_path_basic.c b/libgeda/src/o_path_basic.c index e5b907b..da7270c 100644 --- a/libgeda/src/o_path_basic.c +++ b/libgeda/src/o_path_basic.c @@ -150,11 +150,11 @@ OBJECT *o_path_copy (TOPLEVEL *toplevel, OBJECT *o_current) * \param [in] tb Text buffer containing the path string. * \param [in] release_ver libgeda release version number. * \param [in] fileformat_ver libgeda file format version number. - * \return A pointer to the new path object. + * \return A pointer to the new path object, or NULL on error; */ OBJECT *o_path_read (TOPLEVEL *toplevel, const char *first_line, TextBuffer *tb, - unsigned int release_ver, unsigned int fileformat_ver) + unsigned int release_ver, unsigned int fileformat_ver, GError **err) { OBJECT *new_obj; char type; @@ -174,10 +174,13 @@ OBJECT *o_path_read (TOPLEVEL *toplevel, * The meaning of each item is described in the file format documentation. */ /* Allocate enough space */ - sscanf (first_line, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d\n", - &type, &color, &line_width, &line_end, &line_type, - &line_length, &line_space, &fill_type, &fill_width, &angle1, - &pitch1, &angle2, &pitch2, &num_lines); + if (sscanf (first_line, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d\n", + &type, &color, &line_width, &line_end, &line_type, + &line_length, &line_space, &fill_type, &fill_width, &angle1, + &pitch1, &angle2, &pitch2, &num_lines) != 14) { + g_set_error(err, EDA_ERROR, EDA_ERROR_READ, _("Failed to parse path object\n")); + return NULL; + } /* * Checks if the required color is valid. @@ -200,9 +203,13 @@ OBJECT *o_path_read (TOPLEVEL *toplevel, line = s_textbuffer_next_line (tb); - if (line != NULL) { - pathstr = g_string_append (pathstr, line); + if (line == NULL) { + g_set_error (err, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Premature eof when reading path\n")); + g_free (string); + return NULL; } + + pathstr = g_string_append (pathstr, line); } /* retrieve the character string from the GString */ diff --git a/libgeda/src/o_picture.c b/libgeda/src/o_picture.c index 3119c12..8c1ad2f 100644 --- a/libgeda/src/o_picture.c +++ b/libgeda/src/o_picture.c @@ -44,13 +44,14 @@ * \param [in] tb Text buffer to load embedded data from. * \param [in] release_ver libgeda release version number. * \param [in] fileformat_ver libgeda file format version number. - * \return A pointer to the new picture object. + * \return A pointer to the new picture object, or NULL on error. */ OBJECT *o_picture_read (TOPLEVEL *toplevel, const char *first_line, TextBuffer *tb, unsigned int release_ver, - unsigned int fileformat_ver) + unsigned int fileformat_ver, + GError **err) { OBJECT *new_obj; int x1, y1; @@ -63,14 +64,15 @@ OBJECT *o_picture_read (TOPLEVEL *toplevel, GdkPixbuf *pixbuf = NULL; gchar *file_content = NULL; guint file_length = 0; - GError *err = NULL; + GError *pic_err = NULL; num_conv = sscanf(first_line, "%c %d %d %d %d %d %c %c\n", &type, &x1, &y1, &width, &height, &angle, &mirrored, &embedded); if (num_conv != 8) { - s_log_message (_("Error reading picture definition line: %s.\n"), - first_line); + g_set_error(err, EDA_ERROR, EDA_ERROR_READ, _("Error reading picture definition line: %s.\n"), + first_line); + return NULL; } /* Convert from ascii character to number */ @@ -154,25 +156,25 @@ OBJECT *o_picture_read (TOPLEVEL *toplevel, /* If we have embedded data, try loading from the decoded buffer */ if (file_content != NULL) { - pixbuf = o_picture_pixbuf_from_buffer (file_content, file_length, &err); + pixbuf = o_picture_pixbuf_from_buffer (file_content, file_length, &pic_err); if (err != NULL) { s_log_message (_("Failed to load image from embedded data [%s]: %s\n"), - filename, err->message); + filename, pic_err->message); s_log_message (_("Falling back to file loading. Picture unembedded.\n")); - g_error_free (err); - err = NULL; + g_error_free (pic_err); + pic_err = NULL; embedded = 0; } } /* If we haven't loaded the pixbuf above, try loading from file */ if (pixbuf == NULL) { - pixbuf = gdk_pixbuf_new_from_file (filename, &err); + pixbuf = gdk_pixbuf_new_from_file (filename, &pic_err); if (err != NULL) { s_log_message (_("Failed to load image from file [%s]: %s\n"), - filename, err->message); - g_error_free (err); - err = NULL; + filename, pic_err->message); + g_error_free (pic_err); + pic_err = NULL; } } diff --git a/libgeda/src/o_pin_basic.c b/libgeda/src/o_pin_basic.c index ef91efb..8186b08 100644 --- a/libgeda/src/o_pin_basic.c +++ b/libgeda/src/o_pin_basic.c @@ -142,10 +142,10 @@ void o_pin_recalc(TOPLEVEL *toplevel, OBJECT *o_current) * \param [in] buf a text buffer (usually a line of a schematic file) * \param [in] release_ver The release number gEDA * \param [in] fileformat_ver a integer value of the file format - * \return The object list + * \return The object list, or NULL on error. */ OBJECT *o_pin_read (TOPLEVEL *toplevel, char buf[], - unsigned int release_ver, unsigned int fileformat_ver) + unsigned int release_ver, unsigned int fileformat_ver, GError **err) { OBJECT *new_obj; char type; @@ -156,12 +156,18 @@ OBJECT *o_pin_read (TOPLEVEL *toplevel, char buf[], int whichend; if (release_ver <= VERSION_20020825) { - sscanf (buf, "%c %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color); + if (sscanf (buf, "%c %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color) != 6) { + g_set_error(err, EDA_ERROR, EDA_ERROR_READ, _("Failed to parse pin object\n")); + return NULL; + } pin_type = PIN_TYPE_NET; whichend = -1; } else { - sscanf (buf, "%c %d %d %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, - &color, &pin_type, &whichend); + if (sscanf (buf, "%c %d %d %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, + &color, &pin_type, &whichend) != 8) { + g_set_error(err, EDA_ERROR, EDA_ERROR_READ, _("Failed to parse pin object\n")); + return NULL; + } } if (whichend == -1) { diff --git a/libgeda/src/o_text_basic.c b/libgeda/src/o_text_basic.c index a46137c..ff8a8a5 100644 --- a/libgeda/src/o_text_basic.c +++ b/libgeda/src/o_text_basic.c @@ -325,13 +325,14 @@ void o_text_recalc(TOPLEVEL *toplevel, OBJECT *o_current) * \param [in] tb a text buffer (usually a line of a schematic file) * \param [in] release_ver The release number gEDA * \param [in] fileformat_ver a integer value of the file format - * \return The object list + * \return The object list, or NULL on error. */ OBJECT *o_text_read (TOPLEVEL *toplevel, const char *first_line, TextBuffer *tb, unsigned int release_ver, - unsigned int fileformat_ver) + unsigned int fileformat_ver, + GError **err) { OBJECT *new_obj; char type; @@ -348,24 +349,33 @@ OBJECT *o_text_read (TOPLEVEL *toplevel, GString *textstr; if (fileformat_ver >= 1) { - sscanf(first_line, "%c %d %d %d %d %d %d %d %d %d\n", &type, &x, &y, - &color, &size, - &visibility, &show_name_value, - &angle, &alignment, &num_lines); + if (sscanf(first_line, "%c %d %d %d %d %d %d %d %d %d\n", &type, &x, &y, + &color, &size, + &visibility, &show_name_value, + &angle, &alignment, &num_lines) != 10) { + g_set_error(err, EDA_ERROR, EDA_ERROR_READ, _("Failed to parse text object\n")); + return NULL; + } } else if (release_ver < VERSION_20000220) { /* yes, above less than (not less than and equal) is correct. The format */ /* change occurred in 20000220 */ - sscanf(first_line, "%c %d %d %d %d %d %d %d\n", &type, &x, &y, - &color, &size, - &visibility, &show_name_value, - &angle); + if (sscanf(first_line, "%c %d %d %d %d %d %d %d\n", &type, &x, &y, + &color, &size, + &visibility, &show_name_value, + &angle) != 8) { + g_set_error(err, EDA_ERROR, EDA_ERROR_READ, _("Failed to parse text object\n")); + return NULL; + } alignment = LOWER_LEFT; /* older versions didn't have this */ num_lines = 1; /* only support a single line */ } else { - sscanf(first_line, "%c %d %d %d %d %d %d %d %d\n", &type, &x, &y, - &color, &size, - &visibility, &show_name_value, - &angle, &alignment); + if (sscanf(first_line, "%c %d %d %d %d %d %d %d %d\n", &type, &x, &y, + &color, &size, + &visibility, &show_name_value, + &angle, &alignment) != 9) { + g_set_error (err, EDA_ERROR, EDA_ERROR_READ, _("Failed to parse text object\n")); + return NULL; + } num_lines = 1; /* only support a single line */ } @@ -425,10 +435,13 @@ OBJECT *o_text_read (TOPLEVEL *toplevel, line = s_textbuffer_next_line (tb); - if (line != NULL) - { - textstr = g_string_append (textstr, line); - } + if (line == NULL) { + g_string_free (textstr, TRUE); + g_set_error(err, EDA_ERROR, EDA_ERROR_READ, _("Premature end of data after %d lines\n"), i); + return NULL; + } + + textstr = g_string_append (textstr, line); } /* retrieve the character string from the GString */ string = g_string_free (textstr, FALSE); diff --git a/libgeda/src/scheme_page.c b/libgeda/src/scheme_page.c index 311abb5..c9c986b 100644 --- a/libgeda/src/scheme_page.c +++ b/libgeda/src/scheme_page.c @@ -428,11 +428,18 @@ SCM_DEFINE (string_to_page, "%string->page", 2, 0, 0, free (filename); size_t len; + GError * err = NULL; char *str = scm_to_utf8_stringn (str_s, &len); GList *objects = o_read_buffer (toplevel, NULL, str, len, - page->page_filename); + page->page_filename, &err); free (str); + if (err) { + scm_error (edascm_object_state_sym, s_page_remove_x, + _("Invalid schematic: %s"), scm_list_1 (scm_from_utf8_string (err->message)), SCM_EOL); + g_error_free(err); + } + s_page_append_list (toplevel, page, objects); return edascm_from_page (page); -- 1.7.0.4