]> granicus.if.org Git - graphviz/commitdiff
gv_channel_writer: gracefully handle sizes that exceed INT_MAX
authorMatthew Fernandez <matthew.fernandez@gmail.com>
Sun, 11 Jul 2021 01:40:56 +0000 (18:40 -0700)
committerMatthew Fernandez <matthew.fernandez@gmail.com>
Sat, 17 Jul 2021 18:35:00 +0000 (11:35 -0700)
The compiler (correctly) says:

  gv_tcl_init.c: In function ‘gv_channel_writer’:
  gv_tcl_init.c:25:58: warning: conversion from ‘size_t’ {aka ‘long
    unsigned int’} to ‘int’ may change value [-Wconversion]
       return Tcl_Write((Tcl_Channel)(job->output_file), s, len);
                                                            ^~~
  gv_tcl_init.c:25:12: warning: conversion to ‘size_t’ {aka ‘long unsigned
    int’} from ‘int’ may change the sign of the result [-Wsign-conversion]
       return Tcl_Write((Tcl_Channel)(job->output_file), s, len);
              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This stems from a mismatch between gv_channel_write (or back tracking this, the
write_fn member of GVC) dealing in size_t and the TCL API dealing in int. Prior
to this change, a write of more than INT_MAX through this function would result
in passing a negative value to TCL. I do not know how it responds to such
things. Following this change, a write of more than INT_MAX results in a
truncated write of at most INT_MAX, something callers should already be
anticipating. Squashes two compiler warnings.

tclpkg/gv/gv_tcl_init.c

index 84ff5843e62905f09f62426bc528b35589dc78bf..9e72a82ae482b985856908223fa5e4861bd1e08f 100644 (file)
@@ -13,6 +13,7 @@
 #include <gvc/gvplugin.h>
 #include <gvc/gvcjob.h>
 #include <gvc/gvcint.h>
+#include <limits.h>
 
 static size_t gv_string_writer(GVJ_t *job, const char *s, size_t len)
 {
@@ -22,7 +23,9 @@ static size_t gv_string_writer(GVJ_t *job, const char *s, size_t len)
 
 static size_t gv_channel_writer(GVJ_t *job, const char *s, size_t len)
 {
-    return Tcl_Write((Tcl_Channel)(job->output_file), s, len);
+  // clamp to INT_MAX
+  int l = len > (size_t)INT_MAX ? INT_MAX : (int)len;
+  return (size_t)Tcl_Write((Tcl_Channel)(job->output_file), s, l);
 }
 
 void gv_string_writer_init(GVC_t *gvc)