Blob Blame History Raw
diff -ur cfitsio3430/cfileio.c cfitsio3440/cfileio.c
--- cfitsio3430/cfileio.c	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/cfileio.c	2018-04-11 16:33:41.000000000 +0200
@@ -1490,7 +1490,7 @@
     char oldbinspec[FLEN_FILENAME], oldcolspec[FLEN_FILENAME];
     char cwd[FLEN_FILENAME];
     char tmpStr[FLEN_FILENAME];
-    char tmpinfile[FLEN_FILENAME];
+    char tmpinfile[FLEN_FILENAME]; 
 
     *isopen = 0;
 
@@ -1508,7 +1508,8 @@
 
     if(fits_strcasecmp(urltype,"FILE://") == 0)
       {
-        fits_path2url(infile,tmpinfile,status);
+        if (fits_path2url(infile,FLEN_FILENAME,tmpinfile,status))
+           return (*status);
 
         if(tmpinfile[0] != '/')
           {
@@ -1546,7 +1547,8 @@
 
           if(fits_strcasecmp(oldurltype,"FILE://") == 0)
             {
-              fits_path2url(oldinfile,tmpStr,status);
+              if(fits_path2url(oldinfile,FLEN_FILENAME,tmpStr,status))
+                 return(*status);
               
               if(tmpStr[0] != '/')
                 {
@@ -1856,7 +1858,7 @@
     fitsfile *newptr;
     int ii, hdunum, slen, colnum = -1, testnum, deletecol = 0, savecol = 0;
     int numcols = 0, *colindex = 0, tstatus = 0;
-    char *cptr, *cptr2, *cptr3, *clause = NULL, keyname[FLEN_KEYWORD];
+    char *tstbuff=0, *cptr, *cptr2, *cptr3, *clause = NULL, keyname[FLEN_KEYWORD];
     char colname[FLEN_VALUE], oldname[FLEN_VALUE], colformat[FLEN_VALUE];
     char *file_expr = NULL, testname[FLEN_VALUE], card[FLEN_CARD];
 
@@ -1962,11 +1964,15 @@
 
         if (clause[0] == '!' || clause[0] == '-')
         {
+	    char *clause1 = clause+1;
             /* ===================================== */
             /* Case I. delete this column or keyword */
             /* ===================================== */
 
-            if (ffgcno(*fptr, CASEINSEN, &clause[1], &colnum, status) <= 0)
+	    /* Check that clause does not have leading '#' and
+	       that column name exists */
+            if (clause1[0] && clause1[0] != '#' &&
+		ffgcno(*fptr, CASEINSEN, clause1, &colnum, status) <= 0)
             {
                 /* a column with this name exists, so try to delete it */
                 if (ffdcol(*fptr, colnum, status) > 0)
@@ -1984,18 +1990,41 @@
             }
             else
             {
+	      int delall = 0, clen = 0;
 	        ffcmsg();   /* clear previous error message from ffgcno */
                 /* try deleting a keyword with this name */
                 *status = 0;
-                if (ffdkey(*fptr, &clause[1], status) > 0)
-                {
-                    ffpmsg("column or keyword to be deleted does not exist:");
-                    ffpmsg(clause);
-                    if( colindex ) free( colindex );
-                    if( file_expr ) free( file_expr );
-		    if( clause ) free(clause);
-                    return(*status);
-                }
+		/* skip past leading '#' if any */
+		if (clause1[0] == '#') clause1++;
+		clen = strlen(clause1);
+
+		/* Repeat deletion of keyword if requested with trailing '+' */
+		if (clen > 1 && clause1[clen-1] == '+') {
+		  delall = 1;
+		  clause1[clen-1] = 0;
+		}
+		/* Single or repeated deletions until done */
+		do {
+		  if (ffdkey(*fptr, clause1, status) > 0)
+		    {
+		      if (delall && *status == KEY_NO_EXIST &&
+			  (strchr(clause1,'*') || strchr(clause1,'?')) ) {
+			/* Found last wildcard item. Stop deleting */
+			ffcmsg();
+			*status = 0;
+			delall = 0; /* Force end of this loop */
+		      } else {
+			/* This was not a wildcard deletion, or it resulted in
+			   another kind of error */
+			ffpmsg("column or keyword to be deleted does not exist:");
+			ffpmsg(clause1);
+			if( colindex ) free( colindex );
+			if( file_expr ) free( file_expr );
+			if( clause ) free(clause);
+			return(*status);
+		      }
+		    }
+		} while(delall); /* end do{} */
             }
         }
         else
@@ -2011,17 +2040,32 @@
 	       calculation expression (case 2B) */
             /* ===================================================== */
             cptr2 = clause;
-            slen = fits_get_token(&cptr2, "( =", colname, NULL);
+            slen = fits_get_token2(&cptr2, "( =", &tstbuff, NULL, status);
 
-            if (slen == 0)
+            if (slen == 0 || *status)
             {
-                ffpmsg("error: column or keyword name is blank:");
+                ffpmsg("error: column or keyword name is blank (ffedit_columns):");
                 ffpmsg(clause);
                 if( colindex ) free( colindex );
                 if( file_expr ) free( file_expr );
 		if (clause) free(clause);
+                if (*status==0)
+                   *status=URL_PARSE_ERROR;
+                return(*status);
+            }
+            if (strlen(tstbuff) > FLEN_VALUE-1)
+            {
+                ffpmsg("error: column or keyword name is too long (ffedit_columns):");
+                ffpmsg(clause);
+                if( colindex ) free( colindex );
+                if( file_expr ) free( file_expr );
+		if (clause) free(clause);
+                free(tstbuff);
                 return(*status= URL_PARSE_ERROR);
             }
+            strcpy(colname, tstbuff);
+            free(tstbuff);
+            tstbuff=0;
 
 	    /* If this is a keyword of the form 
 	         #KEYWORD# 
@@ -2091,9 +2135,22 @@
             */
             if (*cptr2  == '(')
             {
-                fits_get_token(&cptr2, ")", oldname, NULL);
-                strcat(colname, oldname);
+                fits_get_token2(&cptr2, ")", &tstbuff, NULL, status);
+                if (*status || (strlen(tstbuff) + strlen(colname) + 1) >
+                     FLEN_VALUE-1)
+                {
+                   ffpmsg("error: column name is too long (ffedit_columns):");
+                   if( file_expr ) free( file_expr );
+		   if (clause) free(clause);
+                   free(tstbuff);
+                   if (*status==0)
+                      *status=URL_PARSE_ERROR;
+		   return (*status);
+                }
+                strcat(colname, tstbuff);
                 strcat(colname, ")");
+                free(tstbuff);
+                tstbuff=0;
                 cptr2++;
             }
 
@@ -2177,7 +2234,20 @@
                 while (*cptr2 == ' ')
                       cptr2++;       /* skip white space */
 
-                fits_get_token(&cptr2, " ", oldname, NULL);
+                fits_get_token2(&cptr2, " ", &tstbuff, NULL, status);
+                if (*status || strlen(tstbuff) > FLEN_VALUE-1)
+                {
+                   ffpmsg("error: column name syntax is too long (ffedit_columns):");
+                   if( file_expr ) free( file_expr );
+		   if (clause) free(clause);
+                   free(tstbuff);
+                   if (*status==0)
+                      *status=URL_PARSE_ERROR;
+		   return (*status);
+                }
+                strcpy(oldname, tstbuff);
+                free(tstbuff);
+                tstbuff=0;
 
                 /* get column number of the existing column */
                 if (ffgcno(*fptr, CASEINSEN, oldname, &colnum, status) <= 0)
@@ -2232,12 +2302,40 @@
                 colformat[0] = '\0';
                 cptr3 = colname;
 
-                fits_get_token(&cptr3, "(", oldname, NULL);
+                fits_get_token2(&cptr3, "(", &tstbuff, NULL, status);
+                if (*status || strlen(tstbuff) > FLEN_VALUE-1)
+                {
+                      ffpmsg("column expression is too long (ffedit_columns)");
+                      if( colindex ) free( colindex );
+                      if( file_expr ) free( file_expr );
+		      if (clause) free(clause);
+                      free(tstbuff);
+                      if (*status==0)
+                         *status=URL_PARSE_ERROR;
+                      return(*status);
+                }
+                strcpy(oldname, tstbuff);
+                free(tstbuff);
+                tstbuff=0;
 
                 if (cptr3[0] == '(' )
                 {
                    cptr3++;  /* skip the '(' */
-                   fits_get_token(&cptr3, ")", colformat, NULL);
+                   fits_get_token2(&cptr3, ")", &tstbuff, NULL, status);
+                   if (*status || strlen(tstbuff) > FLEN_VALUE-1)
+                   {
+                         ffpmsg("column expression is too long (ffedit_columns)");
+                         if( colindex ) free( colindex );
+                         if( file_expr ) free( file_expr );
+		         if (clause) free(clause);
+                         free(tstbuff);
+                         if (*status==0)
+                            *status=URL_PARSE_ERROR;
+                         return(*status);
+                   }
+                   strcpy(colformat, tstbuff);
+                   free(tstbuff);
+                   tstbuff=0;
                 }
 
                 /* calculate values for the column or keyword */
@@ -3282,13 +3380,24 @@
 */
 {
     int slen, isanumber;
-    char token[FLEN_VALUE];
+    char token[FLEN_VALUE], *tstbuff=0;
 
     if (*status > 0)
         return(*status);
 
-    slen = fits_get_token(ptr, " ,:", token, &isanumber); /* get 1st token */
-
+    slen = fits_get_token2(ptr, " ,:", &tstbuff, &isanumber, status); /* get 1st token */
+    if (*status || strlen(tstbuff) > FLEN_VALUE-1)
+    {
+       ffpmsg("Error: image section string too long (fits_get_section_range)");
+       free(tstbuff);
+       if (*status==0)
+          *status = URL_PARSE_ERROR;
+       return(*status);
+    }
+    strcpy(token, tstbuff);
+    free(tstbuff);
+    tstbuff=0;
+    
     /* support [:2,:2] type syntax, where the leading * is implied */
     if (slen==0) strcpy(token,"*");
 
@@ -3311,8 +3420,18 @@
       *secmin = atol(token);
 
       (*ptr)++;  /* skip the colon between the min and max values */
-      slen = fits_get_token(ptr, " ,:", token, &isanumber); /* get token */
-
+      slen = fits_get_token2(ptr, " ,:", &tstbuff, &isanumber, status); /* get token */
+      if (*status || strlen(tstbuff) > FLEN_VALUE-1)
+      {
+         ffpmsg("Error: image section string too long (fits_get_section_range)");
+         free(tstbuff);
+         if (*status==0)
+            *status = URL_PARSE_ERROR;
+         return(*status);
+      }
+      strcpy(token, tstbuff);
+      free(tstbuff);
+      tstbuff=0;
       if (slen == 0 || !isanumber)
         return(*status = URL_PARSE_ERROR);   
 
@@ -3323,7 +3442,18 @@
     if (**ptr == ':')
     {
         (*ptr)++;  /* skip the colon between the max and incre values */
-        slen = fits_get_token(ptr, " ,", token, &isanumber); /* get token */
+        slen = fits_get_token2(ptr, " ,", &tstbuff, &isanumber, status); /* get token */
+        if (*status || strlen(tstbuff) > FLEN_VALUE-1)
+        {
+           ffpmsg("Error: image section string too long (fits_get_section_range)");
+           free(tstbuff);
+           if (*status==0)
+              *status = URL_PARSE_ERROR;
+           return(*status);
+        }
+        strcpy(token, tstbuff);
+        free(tstbuff);
+        tstbuff=0;
 
         if (slen == 0 || !isanumber)
             return(*status = URL_PARSE_ERROR);   
@@ -5063,9 +5193,14 @@
            /* to the output file, and is not the urltype of the input file */
            ptr2 = 0;   /* so reset pointer to zero */
         }
-
+        
         if (ptr2)            /* copy the explicit urltype string */ 
         {
+            if (ptr2-ptr1+3 >= MAX_PREFIX_LEN)
+            {
+               ffpmsg("Name of urltype is too long.");
+               return(*status = URL_PARSE_ERROR);
+            }
             if (urltype)
                  strncat(urltype, ptr1, ptr2 - ptr1 + 3);
             ptr1 = ptr2 + 3;
diff -ur cfitsio3430/drvrfile.c cfitsio3440/drvrfile.c
--- cfitsio3430/drvrfile.c	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/drvrfile.c	2018-04-11 16:33:41.000000000 +0200
@@ -358,7 +358,7 @@
 	/* Get the current working directory */
 	fits_get_cwd(cwd, &status);  
 	slen = strlen(cwd);
-	if (cwd[slen-1] != '/') strcat(cwd,"/"); /* make sure the CWD ends with slash */
+	if ((slen < FLEN_FILENAME) && cwd[slen-1] != '/') strcat(cwd,"/"); /* make sure the CWD ends with slash */
 
 
 	/* check that CWD string matches the rootstring */
@@ -370,6 +370,7 @@
 
 	    /* get the user name from CWD (it follows the root string) */
 	    strncpy(username, cwd+rootlen, 50);  /* limit length of user name */
+            username[50]=0;
 	    cpos=strchr(username, '/');
 	    if (!cpos) {
                ffpmsg("invalid CWD: not equal to root data directory + username");
@@ -765,7 +766,7 @@
     /* Open file.  Try various suffix combinations */  
     if (file_openfile(filename, 0, &diskfile))
     {
-      if (strlen(filename) > FLEN_FILENAME - 1)
+      if (strlen(filename) > FLEN_FILENAME - 5)
           return(0);
 
       strcpy(tmpfilename,filename);
@@ -773,7 +774,7 @@
       if (file_openfile(filename, 0, &diskfile))
       {
 #if HAVE_BZIP2
-        strcpy(tmpfilename,filename);
+        strcpy(filename,tmpfilename);
         strcat(filename,".bz2");
         if (file_openfile(filename, 0, &diskfile))
         {
diff -ur cfitsio3430/drvrgsiftp.c cfitsio3440/drvrgsiftp.c
--- cfitsio3430/drvrgsiftp.c	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/drvrgsiftp.c	2018-04-11 16:33:41.000000000 +0200
@@ -2,7 +2,7 @@
 /*  This file, drvrgsiftp.c contains driver routines for gsiftp files. */
 /*  Andrea Barisani <lcars@si.inaf.it>                                 */
 /* Taffoni Giuliano <taffoni@oats.inaf.it>                             */
-#ifdef HAVE_NET_SERVICES
+#ifdef HAVE_NET_SERVICES 
 #ifdef HAVE_GSIFTP
 
 #include <sys/types.h>
@@ -21,6 +21,7 @@
 
 static int gsiftpopen = 0;
 static int global_offset = 0;
+static int free_gsiftp_tmp=0;
 static int gsiftp_get(char *filename, FILE **gsiftpfile, int num_streams);
 
 static globus_mutex_t lock;
@@ -45,7 +46,9 @@
         ffpmsg("Cannot create temporary directory!");
         return (FILE_NOT_OPENED);
     }
-    gsiftp_tmpfile = malloc(strlen(gsiftp_tmpdir) + strlen("/gsiftp_buffer.tmp"));
+    gsiftp_tmpfile = malloc(strlen(gsiftp_tmpdir) + strlen("/gsiftp_buffer.tmp")+1);
+    gsiftp_tmpfile[0]=0;
+    free_gsiftp_tmp=1;
     strcat(gsiftp_tmpfile, gsiftp_tmpdir);
     strcat(gsiftp_tmpfile, "/gsiftp_buffer.tmp");
   }
@@ -56,8 +59,8 @@
 int gsiftp_shutdown(void)
 {
   free(gsiftpurl);
-  free(gsiftp_tmpfile);
-  free(gsiftp_tmpdir);
+  if (free_gsiftp_tmp)
+     free(gsiftp_tmpfile);
 
   return file_shutdown();
 }
@@ -356,6 +359,11 @@
     done = GLOBUS_FALSE;
 
     strcpy(gsiurl,"gsiftp://");
+    if (strlen(gsiurl)+strlen(filename) > MAXLEN-1)
+    {
+       ffpmsg("file name too long (gsiftp_get)");
+       return (FILE_NOT_OPENED);
+    }
     strcat(gsiurl,filename);
 
     *gsiftpfile = fopen(gsiftp_tmpfile,"w+");
@@ -448,6 +456,11 @@
     done = GLOBUS_FALSE;
     
     strcpy(gsiurl,"gsiftp://");
+    if (strlen(gsiurl)+strlen(filename) > MAXLEN-1)
+    {
+       ffpmsg("file name too long (gsiftp_put)");
+       return (FILE_NOT_OPENED);
+    }
     strcat(gsiurl,filename);
 
     *gsiftpfile = fopen(gsiftp_tmpfile,"r");
diff -ur cfitsio3430/drvrnet.c cfitsio3440/drvrnet.c
--- cfitsio3430/drvrnet.c	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/drvrnet.c	2018-04-11 16:33:41.000000000 +0200
@@ -920,6 +920,12 @@
              /* return the new URL string, and set contentencoding to "ftp" as
 	        a flag to the http_checkfile routine
 	     */
+             if (strlen(scratchstr2) > FLEN_FILENAME-1) 
+             {
+                ffpmsg("Error: redirected url string too long (http_open_network)");
+                fclose(*httpfile);
+                return URL_PARSE_ERROR;
+             }
 	     strcpy(url, scratchstr2);
              strcpy(contentencoding,"ftp://");
 	     fclose (*httpfile); 
@@ -935,6 +941,12 @@
              /* return the new URL string, and set contentencoding to "https" as
 	        a flag to the http_checkfile routine
 	     */
+             if (strlen(scratchstr2) > FLEN_FILENAME-1) 
+             {
+                ffpmsg("Error: redirected url string too long (http_open_network)");
+                fclose(*httpfile);
+                return URL_PARSE_ERROR;
+             }
              strcpy(url, scratchstr2);
              strcpy(contentencoding,"https://");
              fclose(*httpfile);
@@ -973,6 +985,12 @@
 	/* Found the : */
 	scratchstr++; /* skip the : */
 	scratchstr++; /* skip the extra space */
+        if (strlen(scratchstr) > SHORTLEN-1) 
+        {
+           ffpmsg("Error: content-encoding string too long (http_open_network)");
+           fclose(*httpfile);
+           return URL_PARSE_ERROR;
+        }
 	strcpy(contentencoding,scratchstr);
       }
     }
@@ -2556,6 +2574,11 @@
     if ((thost = strchr(urlcopy, '@')) != NULL)
       urlcopy = thost+1;
 
+    if (strlen(urlcopy) > SHORTLEN-1)
+    {
+       free(urlcopyorig);
+       return 1;
+    }
     strcpy(host,urlcopy);
     thost = host;
     while (*urlcopy != '/' && *urlcopy != ':' && *urlcopy) {
@@ -2572,6 +2595,11 @@
     }
   } else {
     /* do this for ftp */
+    if (strlen(urlcopy) > SHORTLEN-1)
+    {
+       free(urlcopyorig);
+       return 1;
+    }
     strcpy(host,urlcopy);
     thost = host;
     while (*urlcopy != '/' && *urlcopy) {
@@ -2585,6 +2613,11 @@
   /* Now the rest is a fn */
 
   if (*urlcopy) {
+    if (strlen(urlcopy) > MAXLEN-1)
+    {
+       free(urlcopyorig);
+       return 1;
+    }
     strcpy(fn,urlcopy);
   }
   free(urlcopyorig);
@@ -2645,7 +2678,11 @@
   if (!strstr(infile,".gz") && (!strstr(infile,".Z"))) {
     /* The infile string does not contain the name of a compressed file.  */
     /* Fisrt, look for a .gz compressed version of the file. */
-      
+    
+    if (strlen(infile) + 3 > MAXLEN-1)
+    {
+       return URL_PARSE_ERROR;
+    }  
     strcpy(newinfile,infile);
     strcat(newinfile,".gz");
 
@@ -2700,7 +2737,11 @@
 
    if (!foundfile) {
     /* did not find .gz compressed version of the file, so look for .Z file. */
-      
+    
+    if (strlen(infile+2) > MAXLEN-1)
+    {
+       return URL_PARSE_ERROR;
+    }  
     strcpy(newinfile,infile);
     strcat(newinfile,".Z");
     if (!http_open_network(newinfile,&httpfile,contentencoding,
@@ -2878,6 +2919,10 @@
     /* The infile string does not contain the name of a compressed file.  */
     /* Fisrt, look for a .gz compressed version of the file. */
       
+    if (strlen(infile)+3 > MAXLEN-1)
+    {
+       return URL_PARSE_ERROR;
+    }
     strcpy(newinfile,infile);
     strcat(newinfile,".gz");
  
@@ -2888,6 +2933,10 @@
     }
 
     if (!foundfile) {
+      if (strlen(infile)+2 > MAXLEN-1)
+      {
+         return URL_PARSE_ERROR;
+      }
       strcpy(newinfile,infile);
       strcat(newinfile,".Z");
  
@@ -3312,6 +3361,11 @@
   
   
   /* Parse the URL apart again */
+  if (strlen(url)+7 > MAXLEN-1)
+  {
+     ffpmsg("Error: url too long");
+     return(FILE_NOT_OPENED);
+  }
   strcpy(turl,"root://");
   strcat(turl,url);
   if (NET_ParseUrl(turl,proto,host,&port,fn)) {
@@ -3329,6 +3383,11 @@
   
   /* get the username */
   if (NULL != getenv("ROOTUSERNAME")) {
+    if (strlen(getenv("ROOTUSERNAME")) > MAXLEN-1)
+    {
+       ffpmsg("root user name too long (root_openfile)");
+       return (FILE_NOT_OPENED);
+    }
     strcpy(recbuf,getenv("ROOTUSERNAME"));
   } else {
     printf("Username: ");
@@ -3357,6 +3416,11 @@
 
   /* now the password */
   if (NULL != getenv("ROOTPASSWORD")) {
+    if (strlen(getenv("ROOTPASSWORD")) > MAXLEN-1)
+    {
+       ffpmsg("root password too long (root_openfile)");
+       return (FILE_NOT_OPENED);
+    }
     strcpy(recbuf,getenv("ROOTPASSWORD"));
   } else {
     printf("Password: ");
@@ -3387,6 +3451,11 @@
   }
   
   /* now the file open request */
+  if (strlen(fn)+strlen(rwmode)+1 > MAXLEN-1)
+  {
+     ffpmsg("root file name too long (root_openfile)");
+     return (FILE_NOT_OPENED);
+  }
   strcpy(recbuf,fn);
   strcat(recbuf," ");
   strcat(recbuf,rwmode);
diff -ur cfitsio3430/editcol.c cfitsio3440/editcol.c
--- cfitsio3430/editcol.c	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/editcol.c	2018-04-11 16:33:41.000000000 +0200
@@ -1097,6 +1097,11 @@
     delbyte = 0;
     for (ii = 0; ii < ncols; ii++)
     {
+        if (strlen(tform[ii]) > FLEN_VALUE-1)
+        {
+           ffpmsg("Column format string too long (fficls)");
+           return (*status=BAD_TFORM);
+        }
         strcpy(tfm, tform[ii]);
         ffupch(tfm);         /* make sure format is in upper case */
 
diff -ur cfitsio3430/eval_f.c cfitsio3440/eval_f.c
--- cfitsio3430/eval_f.c	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/eval_f.c	2018-04-11 16:33:41.000000000 +0200
@@ -593,7 +593,7 @@
          if( parInfo==NULL || *parInfo=='\0' ) {
             /*  Figure out best default column type  */
             if( gParse.hdutype==BINARY_TBL ) {
-               snprintf(tform,16,"%ld",nelem);
+               snprintf(tform,15,"%ld",nelem);
                switch( Info.datatype ) {
                case TLOGICAL:  strcat(tform,"L");  break;
                case TLONG:     strcat(tform,"J");  break;
diff -ur cfitsio3430/fitscore.c cfitsio3440/fitscore.c
--- cfitsio3430/fitscore.c	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/fitscore.c	2018-04-11 16:33:41.000000000 +0200
@@ -976,21 +977,21 @@
               (int) (ii+1), (int) card[ii] );
 
             if (card[ii] == 0)
-	        strcat(msg, " (NULL char.)");
+	        strncat(msg, " (NULL char.)",FLEN_ERRMSG-strlen(msg)-1);
             else if (card[ii] == 9)
-	        strcat(msg, " (TAB char.)");
+	        strncat(msg, " (TAB char.)",FLEN_ERRMSG-strlen(msg)-1);
             else if (card[ii] == 10)
-	        strcat(msg, " (Line Feed char.)");
+	        strncat(msg, " (Line Feed char.)",FLEN_ERRMSG-strlen(msg)-1);
             else if (card[ii] == 11)
-	        strcat(msg, " (Vertical Tab)");
+	        strncat(msg, " (Vertical Tab)",FLEN_ERRMSG-strlen(msg)-1);
             else if (card[ii] == 12)
-	        strcat(msg, " (Form Feed char.)");
+	        strncat(msg, " (Form Feed char.)",FLEN_ERRMSG-strlen(msg)-1);
             else if (card[ii] == 13)
-	        strcat(msg, " (Carriage Return)");
+	        strncat(msg, " (Carriage Return)",FLEN_ERRMSG-strlen(msg)-1);
             else if (card[ii] == 27)
-	        strcat(msg, " (Escape char.)");
+	        strncat(msg, " (Escape char.)",FLEN_ERRMSG-strlen(msg)-1);
             else if (card[ii] == 127)
-	        strcat(msg, " (Delete char.)");
+	        strncat(msg, " (Delete char.)",FLEN_ERRMSG-strlen(msg)-1);
 
             ffpmsg(msg);
 
@@ -1118,6 +1119,13 @@
 	    /* for now at least, treat all cases as an implicit ESO HIERARCH keyword. */
 	    /* This could  change if FITS is ever expanded to directly support longer keywords. */
 	    
+            if (namelen + 11 > FLEN_CARD-1)
+            {
+                ffpmsg(
+               "The following keyword is too long to fit on a card:");
+                ffpmsg(keyname);
+                return(*status = BAD_KEYCHAR);
+            }
             strcat(card, "HIERARCH ");
             strcat(card, tmpname);
 	    namelen += 9;
@@ -1293,7 +1301,6 @@
 /*
   Construct a keyword name string by appending the index number to the root.
   e.g., if root = "TTYPE" and value = 12 then keyname = "TTYPE12".
-  Note: this allows keyword names longer than 8 characters.
 */
 {
     char suffix[16];
@@ -1312,7 +1319,9 @@
         rootlen--;                 /* remove trailing spaces in root name */
         keyname[rootlen] = '\0';
     }
-
+    if (strlen(suffix) + strlen(keyname) > 8)
+       return (*status=206);
+       
     strcat(keyname, suffix);    /* append suffix to the root */
     return(*status);
 }
@@ -1582,7 +1591,7 @@
 {
     char keyname[FLEN_KEYWORD], value[140], comment[140];
     char *tok, *suffix, *loc, tvalue[140];
-    int len, vlen, more, tstatus;
+    int len, vlen, more, tstatus, lentok1=0, remainlen=0;
     double dval;
 
     if (*status > 0)
@@ -1619,36 +1628,41 @@
         tok++;
         len = strspn(tok, " ");  /* no. of spaces before keyword */
         tok += len;
-        if (len < 8)  /* not a blank name? */
-        {
-          len = strcspn(tok, " =");  /* length of name */
-          if (len >= FLEN_KEYWORD)
-            return(*status = BAD_KEYCHAR);
+        
+        len = strcspn(tok, " =+");  /* length of name */
+        if (len >= FLEN_KEYWORD)
+          return(*status = BAD_KEYCHAR);
 
-          strncat(card, tok, len);
+        lentok1 = len;
+        strncat(card, tok, len);
 
-          /*
-            The HIERARCH convention supports non-standard characters
-            in the keyword name, so don't always convert to upper case or
-            abort if there are illegal characters in the name or if the
-            name is greater than 8 characters long.
-          */
+        /*
+          The HIERARCH convention supports non-standard characters
+          in the keyword name, so don't always convert to upper case or
+          abort if there are illegal characters in the name or if the
+          name is greater than 8 characters long.
+        */
 
-          if (len < 9)  /* this is possibly a normal FITS keyword name */
+        if (len < 9)  /* this is possibly a normal FITS keyword name */
+        {
+          ffupch(card);
+          tstatus = 0;
+          if (fftkey(card, &tstatus) > 0)
           {
-            ffupch(card);
-            tstatus = 0;
-            if (fftkey(card, &tstatus) > 0)
-            {
-               /* name contained non-standard characters, so reset */
-               card[0] = '\0';
-               strncat(card, tok, len);
-            }
+             /* name contained non-standard characters, so reset */
+             card[0] = '\0';
+             strncat(card, tok, len);
           }
-
-          tok += len;
         }
 
+        tok += len;
+
+	/* Check optional "+" indicator to delete multiple keywords */
+	if (tok[0] == '+' && len < FLEN_KEYWORD) {
+	  strcat(card, "+");
+	  return (*status);
+	}
+
         /* second token, if present, is the new name for the keyword */
 
         len = strspn(tok, " ");  /* no. of spaces before next token */
@@ -1659,13 +1673,24 @@
 
         *hdtype = -2;
         len = strcspn(tok, " ");  /* length of new name */
-        if (len > 40)  /* name has to fit on columns 41-80 of card */
-          return(*status = BAD_KEYCHAR);
+        /* this name has to fit on columns 41-80 of card,
+           and first name must now fit in 1-40 */
+        if (lentok1 > 40)
+        {
+           card[0] = '\0';
+           return (*status = BAD_KEYCHAR);
+        }
+        if (len > 40)
+        {
+           card[0] = '\0'; 
+           return(*status = BAD_KEYCHAR);
+        }
 
         /* copy the new name to card + 40;  This is awkward, */
         /* but is consistent with the way the Fortran FITSIO works */
 	strcat(card,"                                        ");
-        strncpy(&card[40], tok, len+1); /* copy len+1 to get terminator */
+        strncpy(&card[40], tok, len);
+        card[80] = '\0'; /* necessary to add terminator in case len = 40 */
 
         /*
             The HIERARCH convention supports non-standard characters
@@ -1728,7 +1753,7 @@
       {
         *hdtype = 1;   /* simply append COMMENT and HISTORY keywords */
         strcpy(card, keyname);
-        strncat(card, tok, 73);
+        strncat(card, tok, 72);
         return(*status);
       }
 
@@ -1739,12 +1764,16 @@
       if (*tok == '\'') /* is value enclosed in quotes? */
       {
           more = TRUE;
+          remainlen = 139;
           while (more)
           {
             tok++;  /* temporarily move past the quote char */
             len = strcspn(tok, "'");  /* length of quoted string */
             tok--;
-            strncat(value, tok, len + 2); 
+            if (len+2 > remainlen)
+               return (*status=BAD_KEYCHAR);
+            strncat(value, tok, len + 2);
+            remainlen -= (len+2); 
  
             tok += len + 1;
             if (tok[0] != '\'')   /* check there is a closing quote */
@@ -1762,7 +1791,8 @@
       else   /* not a quoted string value */
       {
           len = strcspn(tok, " /"); /* length of value string */
-
+          if (len > 139)
+             return (*status=BAD_KEYCHAR);
           strncat(value, tok, len);
           if (!( (tok[0] == 'T' || tok[0] == 'F') &&
                  (tok[1] == ' ' || tok[1] == '/' || tok[1] == '\0') )) 
@@ -1796,6 +1826,8 @@
             if (*suffix != '\0' && *suffix != ' ' && *suffix != '/')
             { 
               /* value is not a number; must enclose it in quotes */
+              if (len > 137)
+                return (*status=BAD_KEYCHAR);              
               strcpy(value, "'");
               strncat(value, tok, len);
               strcat(value, "'");
@@ -2607,6 +2639,11 @@
     while (tform[ii] != 0 && tform[ii] == ' ') /* find first non-blank char */
          ii++;
 
+    if (strlen(&tform[ii]) > FLEN_VALUE-1)
+    {
+       ffpmsg("Error: ASCII table TFORM code is too long (ffasfm)");
+       return(*status = BAD_TFORM);
+    }
     strcpy(temp, &tform[ii]); /* copy format string */
     ffupch(temp);     /* make sure it is in upper case */
     form = temp;      /* point to start of format string */
@@ -2764,6 +2801,11 @@
         return(*status = BAD_TFORM);
     }
 
+    if (nchar-ii > FLEN_VALUE-1)
+    {
+        ffpmsg("Error: binary table TFORM code is too long (ffbnfm).");
+        return (*status = BAD_TFORM);
+    }
     strcpy(temp, &tform[ii]); /* copy format string */
     ffupch(temp);     /* make sure it is in upper case */
     form = temp;      /* point to start of format string */
@@ -2779,7 +2821,13 @@
     if (ii == 0)
         repeat = 1;  /* no explicit repeat count */
     else
-        sscanf(form,"%ld", &repeat);  /* read repeat count */
+    {
+        if (sscanf(form,"%ld", &repeat) != 1) /* read repeat count */
+        {
+           ffpmsg("Error: Bad repeat format in TFORM (ffbnfm).");
+           return(*status = BAD_TFORM);
+        }  
+    }
 
     /*-----------------------------------------------*/
     /*             determine datatype code           */
@@ -2948,7 +2996,12 @@
         ffpmsg("Error: binary table TFORM code is blank (ffbnfmll).");
         return(*status = BAD_TFORM);
     }
-
+    
+    if (strlen(&tform[ii]) > FLEN_VALUE-1)
+    {
+       ffpmsg("Error: binary table TFORM code is too long (ffbnfmll).");
+       return(*status = BAD_TFORM);
+    }
     strcpy(temp, &tform[ii]); /* copy format string */
     ffupch(temp);     /* make sure it is in upper case */
     form = temp;      /* point to start of format string */
@@ -6559,7 +6612,7 @@
   'len' is the maximum length of the vector in the table (e.g., '1PE(400)')
 */
 {
-    int ii;
+    int ii, lenform=0;
     long tflds;
     LONGLONG length, addr, maxlen, naxis2, jj;
     char comment[FLEN_COMMENT], keyname[FLEN_KEYWORD];
@@ -6598,13 +6651,20 @@
           /* construct the new keyword value */
           strcpy(newform, "'");
           tmp = strchr(tform, '(');  /* truncate old length, if present */
-          if (tmp) *tmp = 0;       
-          strcat(newform, tform);
+          if (tmp) *tmp = 0;
+          lenform = strlen(tform);
 
           /* print as double, because the string-to-64-bit */
           /* conversion is platform dependent (%lld, %ld, %I64d) */
 
           snprintf(lenval,40, "(%.0f)", (double) maxlen);
+          
+          if (lenform+strlen(lenval)+2 > FLEN_VALUE-1)
+          {
+             ffpmsg("Error assembling TFORMn string (ffuptf).");
+             return(*status = BAD_TFORM);
+          }
+          strcat(newform, tform);
 
           strcat(newform,lenval);
           while(strlen(newform) < 9)
@@ -9234,7 +9294,7 @@
     if (errno == ERANGE)
     {
         strcpy(msg,"Range Error in ffc2jj converting string to longlong int: ");
-        strncat(msg,cval,25);
+        strncat(msg,cval,23);
         ffpmsg(msg);
 
         *status = NUM_OVERFLOW;
@@ -9349,6 +9409,12 @@
 
     if (strchr(cval, 'D') || decimalpt == ',')  {
         /* strtod expects a comma, not a period, as the decimal point */
+        if (strlen(cval) > 72)
+        {
+           strcpy(msg,"Error: Invalid string to float in ffc2rr");
+           ffpmsg(msg);
+           return (*status=BAD_C2F);
+        }
         strcpy(tval, cval);
 
         /*  The C language does not support a 'D'; replace with 'E' */
@@ -9419,6 +9485,12 @@
 
     if (strchr(cval, 'D') || decimalpt == ',') {
         /* need to modify a temporary copy of the string before parsing it */
+        if (strlen(cval) > 72)
+        {
+           strcpy(msg,"Error: Invalid string to double in ffc2dd");
+           ffpmsg(msg);
+           return (*status=BAD_C2D);
+        }
         strcpy(tval, cval);
         /*  The C language does not support a 'D'; replace with 'E' */
         if ((loc = strchr(tval, 'D'))) *loc = 'E';
diff -ur cfitsio3430/fpackutil.c cfitsio3440/fpackutil.c
--- cfitsio3430/fpackutil.c	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/fpackutil.c	2018-04-11 23:05:04.000000000 +0200
@@ -63,16 +63,23 @@
 	int status = 0, hdunum;
 	char  msg[SZ_STR];
 
-	fits_file_name(infptr, tempfilename, &status);
-	fits_get_hdu_num(infptr, &hdunum);
-	
-        fits_close_file (infptr, &status);
-
-	snprintf(msg, SZ_STR,"Error processing file: %s\n", tempfilename);
-	fp_msg (msg);
-	snprintf(msg, SZ_STR,"  in HDU number %d\n", hdunum);
-	fp_msg (msg);
-
+        if (infptr)
+        {
+	   fits_file_name(infptr, tempfilename, &status);
+	   fits_get_hdu_num(infptr, &hdunum);
+
+           fits_close_file (infptr, &status);
+
+	   snprintf(msg, SZ_STR,"Error processing file: %s\n", tempfilename);
+	   fp_msg (msg);
+	   snprintf(msg, SZ_STR,"  in HDU number %d\n", hdunum);
+	   fp_msg (msg);
+        }
+        else
+        {
+           snprintf(msg, SZ_STR,"Error: Unable to process input file\n");
+           fp_msg(msg);
+        }
 	fits_report_error (stderr, stat);
 
 	if (outfptr) {
@@ -129,6 +136,13 @@
 
         for (ii = 0; ii < maxtry; ii++) {
 		if (fp_access(tmpnam)) break;  /* good, the file does not exist */
+                if (strlen(tmpnam) > SZ_STR-2)
+                {
+		   fp_msg ("\nCould not create temporary file name:\n");
+		   fp_msg (tmpnam);
+		   fp_msg ("\n");
+		   exit (-1);
+                }
 		strcat(tmpnam, "x");  /* append an x to the name, and try again */
 	}
 
@@ -203,7 +217,8 @@
 	}
 
 	for (iarg=fpvar.firstfile; iarg < argc; iarg++) {
-	    strncpy (infits, argv[iarg], SZ_STR);
+	    strncpy (infits, argv[iarg], SZ_STR-1);
+            infits[SZ_STR-1]=0;
 
 	    if (strchr (infits, '[') || strchr (infits, ']')) {
 		fp_msg ("Error: section/extension notation not supported: ");
@@ -472,6 +487,11 @@
 
 	      /* if gzipping the output, make sure .gz file doesn't exist */
 	      if (fpptr->do_gzip_file) {
+                        if (strlen(outfits)+3 > SZ_STR-1)
+                        {
+		            fp_msg ("Error: output file name too long:\n "); fp_msg (outfits);
+		            fp_msg ("\n "); fp_noop (); exit (-1);
+                        }
 	                strcat(outfits, ".gz");
 	                if (fp_access (outfits) == 0) {
 		            fp_msg ("Error: output file already exists:\n "); fp_msg (outfits);
@@ -486,6 +506,11 @@
 	      /* check that input file  exists */
 	      if (infits[0] != '-') {  /* if not reading from stdin stream */
 	        if (fp_access (infits) != 0) {  /* if not, then check if */
+                    if (strlen(infits)+3 > SZ_STR-1)
+                    {
+		        fp_msg ("Error: input file name too long:\n "); fp_msg (infits);
+		        fp_msg ("\n "); fp_noop (); exit (-1);
+                    }
 		    strcat(infits, ".gz");     /* a gzipped version exsits */
 	            if (fp_access (infits) != 0) {
                         namelen = strlen(infits);
@@ -553,7 +578,8 @@
 {
 	char	infits[SZ_STR], outfits[SZ_STR];
 	char	temp[SZ_STR], answer[30];
-	int	iarg, islossless, namelen, iraf_infile = 0, status = 0, ifail;
+        char    valchar[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.#()+,-_@[]/^{}";
+	int	ichar=0, outlen=0, iarg, islossless, namelen, iraf_infile = 0, status = 0, ifail;
         
 	if (fpvar.initialized != FP_INIT_MAGIC) {
 	    fp_msg ("Error: internal initialization error\n"); exit (-1);
@@ -598,6 +624,7 @@
           islossless = 1;
 
 	  strncpy (infits, argv[iarg], SZ_STR - 1);
+          infits[SZ_STR-1]=0;
 
           if (unpack) {
 	  	/* ********** This section applies to funpack ************ */
@@ -678,6 +705,7 @@
 	  }
 
           strncpy(temp, outfits, SZ_STR-1);
+          temp[SZ_STR-1]=0;
 
 	  if (infits[0] != '-') {  /* if not reading from stdin stream */
              if (!strcmp(infits, outfits) ) {  /* are input and output names the same? */
@@ -828,6 +856,20 @@
 
 	    if (fpvar.do_gzip_file) {       /* gzip the output file */
 		strcpy(temp, "gzip -1 ");
+                outlen = strlen(outfits);
+                if (outlen + 8 > SZ_STR-1)
+                {
+                   fp_msg("\nError: Output file name is too long.\n");
+                   exit(-1);
+                }
+                for (ichar=0; ichar < outlen; ++ichar)
+                {
+                   if (!strchr(valchar, outfits[ichar]))
+                   {
+                      fp_msg("\n Error: Invalid characters in output file name.\n");
+                      exit(-1);
+                   }
+                }                
 		strcat(temp,outfits);
                 system(temp);
 	        strcat(outfits, ".gz");    /* only possibible with funpack */
@@ -1197,11 +1239,12 @@
 		snprintf(dimen,100," (%ld", naxes[0]);
 		len =strlen(dimen);
 		for (ii = 1; ii < naxis; ii++) {
-                    if (len < 100)
+                    if (len < 99)
 		       snprintf(dimen+len,100-len,",%ld", naxes[ii]);
 		    len =strlen(dimen);
 		}
-		strcat(dimen, ")");
+                if (strlen(dimen)<99)
+		   strcat(dimen, ")");
 		printf("%-12s",dimen);
 
 		fits_get_hduaddr(inputfptr, &headstart, &datastart, &dataend, &stat);
diff -ur cfitsio3430/getcols.c cfitsio3440/getcols.c
--- cfitsio3430/getcols.c	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/getcols.c	2018-04-11 16:33:41.000000000 +0200
@@ -296,8 +296,9 @@
 
       /* write the formated string for each value */
       if (nulval) {
-          strcpy(tmpnull, nulval);
-          nulwidth = strlen(nulval);
+          strncpy(tmpnull, nulval,79);
+          tmpnull[79]='\0'; /* In case len(nulval) >= 79 */
+          nulwidth = strlen(tmpnull);
       } else {
           strcpy(tmpnull, " ");
           nulwidth = 1;
@@ -430,8 +431,9 @@
       } 
 
       if (nulval) {
-          strcpy(tmpnull, nulval);
-          nulwidth = strlen(nulval);
+          strncpy(tmpnull, nulval,79);
+          tmpnull[79]='\0';
+          nulwidth = strlen(tmpnull);
       } else {
           strcpy(tmpnull, " ");
           nulwidth = 1;
diff -ur cfitsio3430/getkey.c cfitsio3440/getkey.c
--- cfitsio3430/getkey.c	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/getkey.c	2018-04-11 16:33:42.000000000 +0200
@@ -1451,6 +1451,10 @@
           equalssign = strchr(card, '=');
 	  if (equalssign == 0) continue;  /* keyword has no value */
 
+          if (equalssign - card - lenroot > 7)
+          {
+             return (*status=BAD_KEYCHAR);
+          }
           strncat(keyindex, &card[lenroot], equalssign - card  - lenroot);  /*  copy suffix  */
           tstatus = 0;
           if (ffc2ii(keyindex, &ival, &tstatus) <= 0)     /*  test suffix  */
@@ -1528,6 +1532,10 @@
           equalssign = strchr(card, '=');
 	  if (equalssign == 0) continue;  /* keyword has no value */
 
+          if (equalssign - card - lenroot > 7)
+          {
+             return (*status=BAD_KEYCHAR);
+          }
           strncat(keyindex, &card[lenroot], equalssign - card  - lenroot);  /*  copy suffix  */
 
           tstatus = 0;
@@ -1605,6 +1613,10 @@
           equalssign = strchr(card, '=');
 	  if (equalssign == 0) continue;  /* keyword has no value */
 
+          if (equalssign - card - lenroot > 7)
+          {
+             return (*status=BAD_KEYCHAR);
+          }
           strncat(keyindex, &card[lenroot], equalssign - card  - lenroot);  /*  copy suffix  */
 
           tstatus = 0;
@@ -1682,6 +1694,10 @@
           equalssign = strchr(card, '=');
 	  if (equalssign == 0) continue;  /* keyword has no value */
 
+          if (equalssign - card - lenroot > 7)
+          {
+             return (*status=BAD_KEYCHAR);
+          }
           strncat(keyindex, &card[lenroot], equalssign - card  - lenroot);  /*  copy suffix  */
 
           tstatus = 0;
@@ -1759,6 +1775,10 @@
           equalssign = strchr(card, '=');
 	  if (equalssign == 0) continue;  /* keyword has no value */
 
+          if (equalssign - card - lenroot > 7)
+          {
+             return (*status=BAD_KEYCHAR);
+          }
           strncat(keyindex, &card[lenroot], equalssign - card  - lenroot);  /*  copy suffix  */
 
           tstatus = 0;
@@ -1835,6 +1855,10 @@
           equalssign = strchr(card, '=');
 	  if (equalssign == 0) continue;  /* keyword has no value */
 
+          if (equalssign - card - lenroot > 7)
+          {
+             return (*status=BAD_KEYCHAR);
+          }
           strncat(keyindex, &card[lenroot], equalssign - card  - lenroot);  /*  copy suffix  */
           tstatus = 0;
           if (ffc2ii(keyindex, &ival, &tstatus) <= 0)      /*  test suffix */
diff -ur cfitsio3430/group.c cfitsio3440/group.c
--- cfitsio3430/group.c	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/group.c	2018-04-11 16:33:41.000000000 +0200
@@ -1543,6 +1543,13 @@
 		  else
 		    {
 		      strcpy(memberLocation,cwd);
+                      if (strlen(memberLocation)+strlen(memberFileName)+1 > 
+                                FLEN_FILENAME-1)
+                      {
+                         ffpmsg("member path and filename is too long (ffgtam)");
+                         *status = URL_PARSE_ERROR;
+                         continue;
+                      }
 		      strcat(memberLocation,"/");
 		      strcat(memberLocation,memberFileName);
 		    }
@@ -1565,6 +1572,14 @@
 		  else
 		    {
 		      strcpy(groupLocation,cwd);
+                      if (strlen(groupLocation)+strlen(groupFileName)+1 > 
+                                FLEN_FILENAME-1)
+                      {
+                         ffpmsg("group path and filename is too long (ffgtam)");
+                         *status = URL_PARSE_ERROR;
+                         continue;
+                      }
+                      
 		      strcat(groupLocation,"/");
 		      strcat(groupLocation,groupFileName);
 		    }
@@ -1782,11 +1797,18 @@
 
                     /* make grplc absolute if necessary */
                     if(!fits_is_url_absolute(grplc)) {
-		      fits_path2url(grplc,groupLocation,status);
+		      fits_path2url(grplc,FLEN_FILENAME,groupLocation,status);
 
 		      if(groupLocation[0] != '/')
 			{
 			  strcpy(tmp, cwd);
+                          if (strlen(tmp)+strlen(groupLocation)+1 > 
+                                    FLEN_FILENAME-1)
+                          {
+                             ffpmsg("path and group location is too long (ffgtam)");
+                             *status = URL_PARSE_ERROR;
+                             continue;
+                          }
 			  strcat(tmp,"/");
 			  strcat(tmp,groupLocation);
 			  fits_clean_url(tmp,grplc,status);
@@ -1795,11 +1817,18 @@
 
                     /* make groupFileName absolute if necessary */
                     if(!fits_is_url_absolute(groupFileName)) {
-		      fits_path2url(groupFileName,groupLocation,status);
+		      fits_path2url(groupFileName,FLEN_FILENAME,groupLocation,status);
 
 		      if(groupLocation[0] != '/')
 			{
 			  strcpy(tmp, cwd);
+                          if (strlen(tmp)+strlen(groupLocation)+1 > 
+                                    FLEN_FILENAME-1)
+                          {
+                             ffpmsg("path and group location is too long (ffgtam)");
+                             *status = URL_PARSE_ERROR;
+                             continue;
+                          }
 			  strcat(tmp,"/");
 			  strcat(tmp,groupLocation);
                           /*
@@ -2145,7 +2174,14 @@
 		       &locationCol,&uriCol,&grptype,status);
 
       if(*status != 0) continue;
+      
+      /* verify the column formats */
+      
+      *status = ffvcfm(gfptr,xtensionCol,extnameCol,extverCol,positionCol,
+		       locationCol,uriCol,status);
 
+      if(*status != 0) continue;
+      
       /*
 	 extract the member information from grouping table
       */
@@ -2415,6 +2451,13 @@
 			{
 			  fits_get_cwd(cwd,status);
 			  strcat(cwd,"/");
+                          if (strlen(cwd)+strlen(grpLocation1)+1 > 
+                                    FLEN_FILENAME-1)
+                          {
+                             ffpmsg("cwd and group location1 is too long (ffgmop)");
+                             *status = URL_PARSE_ERROR;
+                             continue;
+                          }
 			  strcat(cwd,grpLocation1);
 			  strcpy(grpLocation1,cwd);
 			}
@@ -2477,6 +2520,13 @@
 			                              *grpLocation2 != '/')
 			{
 			  fits_get_cwd(cwd,status);
+                          if (strlen(cwd)+strlen(grpLocation2)+1 > 
+                                    FLEN_FILENAME-1)
+                          {
+                             ffpmsg("cwd and group location2 is too long (ffgmop)");
+                             *status = URL_PARSE_ERROR;
+                             continue;
+                          }
 			  strcat(cwd,"/");
 			  strcat(cwd,grpLocation2);
 			  strcpy(grpLocation2,cwd);
@@ -3112,6 +3162,13 @@
 		 !fits_is_url_absolute(grpLocation1))
 		{
 		  strcpy(grpLocation3,cwd);
+                  if (strlen(grpLocation3)+strlen(grpLocation1)+1 > 
+                            FLEN_FILENAME-1)
+                  {
+                     ffpmsg("group locations are too long (ffgmrm)");
+                     *status = URL_PARSE_ERROR;
+                     continue;
+                  }
 		  strcat(grpLocation3,"/");
 		  strcat(grpLocation3,grpLocation1);
 		  fits_clean_url(grpLocation3,grpLocation1,status);
@@ -3121,6 +3178,13 @@
 		 !fits_is_url_absolute(grpLocation2))
 		{
 		  strcpy(grpLocation3,cwd);
+                  if (strlen(grpLocation3)+strlen(grpLocation2)+1 > 
+                            FLEN_FILENAME-1)
+                  {
+                     ffpmsg("group locations are too long (ffgmrm)");
+                     *status = URL_PARSE_ERROR;
+                     continue;
+                  }
 		  strcat(grpLocation3,"/");
 		  strcat(grpLocation3,grpLocation2);
 		  fits_clean_url(grpLocation3,grpLocation2,status);
@@ -3225,6 +3289,13 @@
 				*editLocation = '\0';
 			    }
 				
+                          if (strlen(grpLocation3)+strlen(grplc)+1 > 
+                                    FLEN_FILENAME-1)
+                          {
+                             ffpmsg("group locations are too long (ffgmrm)");
+                             *status = URL_PARSE_ERROR;
+                             continue;
+                          }
 			  strcat(grpLocation3,"/");
 			  strcat(grpLocation3,grplc);
 			  *status = fits_clean_url(grpLocation3,grplc,
@@ -3466,6 +3537,87 @@
 }
 
 /*****************************************************************************/
+int ffvcfm(fitsfile *gfptr, int xtensionCol, int extnameCol, int extverCol,
+	   int positionCol, int locationCol, int uriCol, int *status)
+{
+/*
+   Perform validation on column formats to ensure this matches the grouping
+   format the get functions expect.  Particularly want to check widths of
+   string columns.
+*/
+
+   int typecode=0;
+   long repeat=0, width=0;
+   
+   if (*status != 0) return (*status);
+   
+   do {
+       if (xtensionCol)
+       {
+          fits_get_coltype(gfptr, xtensionCol, &typecode, &repeat, &width, status);
+          if (*status || typecode != TSTRING || repeat != width || repeat > 8)
+          {
+             if (*status==0) *status=NOT_GROUP_TABLE;
+             ffpmsg("Wrong format for Grouping xtension col. (ffvcfm)");
+             continue;
+          }          
+       }
+       if (extnameCol)
+       {
+          fits_get_coltype(gfptr, extnameCol, &typecode, &repeat, &width, status);
+          if (*status || typecode != TSTRING || repeat != width || repeat > 32)
+          {
+             if (*status==0) *status=NOT_GROUP_TABLE;
+             ffpmsg("Wrong format for Grouping name col. (ffvcfm)");
+             continue;
+          }          
+       }
+       if (extverCol)
+       {
+          fits_get_coltype(gfptr, extverCol, &typecode, &repeat, &width, status);
+          if (*status || typecode != TINT32BIT ||  repeat > 1)
+          {
+             if (*status==0) *status=NOT_GROUP_TABLE;
+             ffpmsg("Wrong format for Grouping version col. (ffvcfm)");
+             continue;
+          }          
+       }
+       if (positionCol)
+       {
+          fits_get_coltype(gfptr, positionCol, &typecode, &repeat, &width, status);
+          if (*status || typecode != TINT32BIT ||  repeat > 1)
+          {
+             if (*status==0) *status=NOT_GROUP_TABLE;
+             ffpmsg("Wrong format for Grouping position col. (ffvcfm)");
+             continue;
+          }          
+       }
+       if (locationCol)
+       {
+          fits_get_coltype(gfptr, locationCol, &typecode, &repeat, &width, status);
+          if (*status || typecode != TSTRING || repeat != width || repeat > 256)
+          {
+             if (*status==0) *status=NOT_GROUP_TABLE;
+             ffpmsg("Wrong format for Grouping location col. (ffvcfm)");
+             continue;
+          }          
+       }
+       if (uriCol)
+       {
+          fits_get_coltype(gfptr, uriCol, &typecode, &repeat, &width, status);
+          if (*status || typecode != TSTRING || repeat != width || repeat > 3)
+          {
+             if (*status==0) *status=NOT_GROUP_TABLE;
+             ffpmsg("Wrong format for Grouping URI col. (ffvcfm)");
+             continue;
+          }          
+       }
+   } while (0);
+   return (*status);
+}
+
+
+/*****************************************************************************/
 int ffgtdc(int   grouptype,     /* code specifying the type of
 				   grouping table information:
 				   GT_ID_ALL_URI  0 ==> defualt (all columns)
@@ -3977,11 +4129,17 @@
 
   else if(!fits_is_url_absolute(location))
     {
-      fits_path2url(location,tmpLocation,status);
+      fits_path2url(location,FLEN_FILENAME,tmpLocation,status);
 
       if(*tmpLocation != '/')
 	{
 	  fits_get_cwd(cwd,status);
+          if (strlen(cwd)+strlen(tmpLocation)+1 > 
+                    FLEN_FILENAME-1)
+          {
+             ffpmsg("cwd and location are too long (ffgmf)");
+             return (*status = URL_PARSE_ERROR);
+          }
 	  strcat(cwd,"/");
 	  strcat(cwd,tmpLocation);
 	  fits_clean_url(cwd,tmpLocation,status);
@@ -4084,6 +4242,13 @@
 	     *mbrLocation1 != '/')
 	    {
 	      fits_get_cwd(cwd,status);
+              if (strlen(cwd)+strlen(mbrLocation1)+1 > 
+                        FLEN_FILENAME-1)
+              {
+                 ffpmsg("cwd and member locations are too long (ffgmf)");
+                 *status = URL_PARSE_ERROR;
+                 continue;
+              }
 	      strcat(cwd,"/");
 	      strcat(cwd,mbrLocation1);
 	      fits_clean_url(cwd,mbrLocation1,status);
@@ -4094,6 +4259,13 @@
 	     *mbrLocation2 != '/')
 	    {
 	      fits_get_cwd(cwd,status);
+              if (strlen(cwd)+strlen(mbrLocation2)+1 > 
+                        FLEN_FILENAME-1)
+              {
+                 ffpmsg("cwd and member locations are too long (ffgmf)");
+                 *status = URL_PARSE_ERROR;
+                 continue;
+              }
 	      strcat(cwd,"/");
 	      strcat(cwd,mbrLocation2);
 	      fits_clean_url(cwd,mbrLocation2,status);
@@ -4119,6 +4291,13 @@
 	      if(!fits_is_url_absolute(grpLocation1) && *grpLocation1 != '/')
 		{
 		  fits_get_cwd(cwd,status);
+                  if (strlen(cwd)+strlen(grpLocation1)+1 > 
+                            FLEN_FILENAME-1)
+                  {
+                     ffpmsg("cwd and group locations are too long (ffgmf)");
+                     *status = URL_PARSE_ERROR;
+                     continue;
+                  }
 		  strcat(cwd,"/");
 		  strcat(cwd,grpLocation1);
 		  fits_clean_url(cwd,grpLocation1,status);
@@ -4154,6 +4333,13 @@
 	      if(!fits_is_url_absolute(grpLocation2) && *grpLocation2 != '/')
 		{
 		  fits_get_cwd(cwd,status);
+                  if (strlen(cwd)+strlen(grpLocation2)+1 > 
+                            FLEN_FILENAME-1)
+                  {
+                     ffpmsg("cwd and group locations are too long (ffgmf)");
+                     *status = URL_PARSE_ERROR;
+                     continue;
+                  }
 		  strcat(cwd,"/");
 		  strcat(cwd,grpLocation2);
 		  fits_clean_url(cwd,grpLocation2,status);
@@ -4823,6 +5009,8 @@
         Host dependent directory path to/from URL functions
   --------------------------------------------------------------------------*/
 int fits_path2url(char *inpath,  /* input file path string                  */
+                  int maxlength, /* I max number of chars that can be written
+                             to output, including terminating NULL */
 		  char *outpath, /* output file path string                 */
 		  int  *status)
   /*
@@ -5187,7 +5375,7 @@
     encode all "unsafe" and "reserved" URL characters
   */
 
-  *status = fits_encode_url(buff,outpath,status);
+  *status = fits_encode_url(buff,maxlength,outpath,status);
 
   return(*status);
 }
@@ -5473,7 +5661,12 @@
     Good old getcwd() seems to work with all other platforms
   */
 
-  getcwd(buff,FLEN_FILENAME);
+  if (!getcwd(buff,FLEN_FILENAME))
+  {
+     cwd[0]=0;
+     ffpmsg("Path and file name too long (fits_get_cwd)");
+     return (*status=URL_PARSE_ERROR);
+  }
 
 #endif
 
@@ -5481,7 +5674,7 @@
     convert the cwd string to a URL standard path string
   */
 
-  fits_path2url(buff,cwd,status);
+  fits_path2url(buff,FLEN_FILENAME,cwd,status);
 
   return(*status);
 }
@@ -5788,7 +5981,7 @@
 		  i = 0;
 		}
 
-	      *status = fits_path2url(tmpPtr,realURL+i,status);
+	      *status = fits_path2url(tmpPtr,FLEN_FILENAME-i,realURL+i,status);
 	    }
 	}
 
@@ -5810,7 +6003,7 @@
 		  i = 0;
 		}
 
-	      *status = fits_path2url(tmpPtr,startURL+i,status);
+	      *status = fits_path2url(tmpPtr,FLEN_FILENAME-i,startURL+i,status);
 	    }
 	}
 
@@ -5923,6 +6116,14 @@
      * onto output string until stack is empty */
     while(0 < mystack->stack_size) {
       tmp = shift_grp_stack(mystack);
+      if (strlen(outURL) + strlen(tmp) + 1 > FLEN_FILENAME-1)
+      {
+         outURL[0]=0;
+         ffpmsg("outURL is too long (fits_clean_url)");
+         *status = URL_PARSE_ERROR;
+         delete_grp_stack(&mystack);
+         return *status;         
+      }
       strcat(outURL, tmp);
       strcat(outURL, "/");
     }
@@ -6118,10 +6319,25 @@
 	  */
 
 	  for(j = refcount; j < refsize; ++j)
-	    if(refURL[j] == '/') strcat(relURL,"../");
+	    if(refURL[j] == '/') 
+            {
+               if (strlen(relURL)+3 > FLEN_FILENAME-1)
+               {
+	          *status = URL_PARSE_ERROR;
+	          ffpmsg("relURL too long (fits_url2relurl)");
+	          return (*status);
+               }
+               strcat(relURL,"../");
+            }
 	  
 	  /* copy all remaining characters of absURL to the output relURL */
 
+          if (strlen(relURL) + strlen(absURL+abscount) > FLEN_FILENAME-1)
+          {
+	     *status = URL_PARSE_ERROR;
+	     ffpmsg("relURL too long (fits_url2relurl)");
+	     return (*status);
+          }
 	  strcat(relURL,absURL+abscount);
 	  
 	  /* we are done building the relative URL */
@@ -6168,6 +6384,13 @@
 	make a copy of the reference URL string refURL for parsing purposes
       */
 
+      if (strlen(refURL) > FLEN_FILENAME-1)
+      {
+         absURL[0]=0;
+         ffpmsg("ref URL is too long (fits_relurl2url)");
+         *status = URL_PARSE_ERROR;
+         continue;
+      }
       strcpy(tmpStr,refURL);
 
       /*
@@ -6199,6 +6422,13 @@
 	  if(tmpStr1 != NULL) tmpStr1[1] = 0;
 	  else                tmpStr[0]  = 0;
 	  
+          if (strlen(tmpStr)+strlen(relURL) > FLEN_FILENAME-1)
+          {
+              absURL[0]=0;
+              ffpmsg("rel + ref URL is too long (fits_relurl2url)");
+              *status = URL_PARSE_ERROR;
+              continue;
+          }
 	  strcat(tmpStr,relURL);
 	}
       else
@@ -6220,7 +6450,17 @@
 	  
 	  strcpy(absURL,"/");
 	  
-	  for(i = 0; relURL[i] == '/'; ++i) strcat(absURL,"/");
+	  for(i = 0; relURL[i] == '/'; ++i) 
+          {
+             if (strlen(absURL) + 1 > FLEN_FILENAME-1)
+             {
+                 absURL[0]=0;
+                 ffpmsg("abs URL is too long (fits_relurl2url)");
+                 *status = URL_PARSE_ERROR;
+                 return (*status);
+             }
+             strcat(absURL,"/");
+          }
 	  
 	  /*
 	    loop over the refURL string until the slash pattern stored
@@ -6265,6 +6505,13 @@
 	    the absURL
 	   */
 
+          if (strlen(tmpStr)+strlen(relURL) > FLEN_FILENAME-1)
+          {
+              absURL[0]=0;
+              ffpmsg("rel + ref URL is too long (fits_relurl2url)");
+              *status = URL_PARSE_ERROR;
+              continue;
+          }
 	  strcat(tmpStr,relURL);
 	}
 
@@ -6280,7 +6527,9 @@
   return(*status);
 }
 /*--------------------------------------------------------------------------*/
-int fits_encode_url(char *inpath,  /* I URL  to be encoded                  */ 
+int fits_encode_url(char *inpath,  /* I URL  to be encoded                  */
+                    int maxlength, /* I max number of chars that may be copied
+                               to outpath, including terminating NULL. */ 
 		    char *outpath, /* O output encoded URL                  */
 		    int *status)
      /*
@@ -6288,12 +6537,12 @@
        convention, where XX stand for the two hexidecimal digits of the
        encode character's ASCII code.
 
-       Note that the output path is at least as large as, if not larger than
-       the input path, so that OUTPATH should be passed to this function
-       with room for growth. If not a runtime error could result. It is
-       assumed that OUTPATH has been allocated with enough room to hold
-       the resulting encoded URL.
-
+       Note that the outpath length, as specified by the maxlength argument,
+       should be at least as large as inpath and preferably larger (to hold
+       any characters that need encoding).  If more than maxlength chars are 
+       required for outpath, including the terminating NULL, outpath will
+       be set to size 0 and an error status will be returned.
+       
        This function was adopted from code in the libwww.a library available
        via the W3 consortium <URL: http://www.w3.org>
      */
@@ -6303,6 +6552,7 @@
   char *p;
   char *q;
   char *hex = "0123456789ABCDEF";
+  int iout=0;
   
 unsigned const char isAcceptable[96] =
 {/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF */
@@ -6325,7 +6575,7 @@
   
   /* loop over all characters in inpath until '\0' is encountered */
 
-  for(q = outpath, p = inpath; *p; p++)
+  for(q = outpath, p = inpath; *p && (iout < maxlength-1) ; p++)
     {
       a = (unsigned char)*p;
 
@@ -6333,19 +6583,41 @@
 
       if(!( a>=32 && a<128 && (isAcceptable[a-32])))
 	{
-	  /* add a '%' character to the outpath */
-	  *q++ = HEX_ESCAPE;
-	  /* add the most significant ASCII code hex value */
-	  *q++ = hex[a >> 4];
-	  /* add the least significant ASCII code hex value */
-	  *q++ = hex[a & 15];
+           if (iout+2 < maxlength-1)
+           {
+	     /* add a '%' character to the outpath */
+	     *q++ = HEX_ESCAPE;
+	     /* add the most significant ASCII code hex value */
+	     *q++ = hex[a >> 4];
+	     /* add the least significant ASCII code hex value */
+	     *q++ = hex[a & 15];
+             iout += 3;
+           }
+           else
+           {
+              ffpmsg("URL input is too long to encode (fits_encode_url)");
+              *status = URL_PARSE_ERROR;
+              outpath[0] = 0;
+              return (*status);
+           }
 	}
       /* else just copy the character as is */
-      else *q++ = *p;
+      else 
+      {
+         *q++ = *p;
+         iout++;
+      }
     }
 
   /* null terminate the outpath string */
 
+  if (*p && (iout == maxlength-1))
+  {
+     ffpmsg("URL input is too long to encode (fits_encode_url)");
+     *status = URL_PARSE_ERROR;
+     outpath[0] = 0;
+     return (*status);
+  }
   *q++ = 0; 
   
   return(*status);
diff -ur cfitsio3430/group.h cfitsio3440/group.h
--- cfitsio3430/group.h	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/group.h	2018-04-11 16:33:41.000000000 +0200
@@ -23,6 +23,9 @@
 	   int *positionCol, int *locationCol, int *uriCol, int *grptype,
 	   int *status);
 
+int ffvcfm(fitsfile *gfptr, int xtensionCol, int extnameCol, int extverCol,
+	   int positionCol, int locationCol, int uriCol, int *status);
+
 int ffgmul(fitsfile *mfptr, int rmopt, int *status);
 
 int ffgmf(fitsfile *gfptr, char *xtension, char *extname, int extver,	   
@@ -41,7 +44,7 @@
 
 void prepare_keyvalue(char *keyvalue);
 
-int fits_path2url(char *inpath, char *outpath, int  *status);
+int fits_path2url(char *inpath, int maxlength, char *outpath, int  *status);
 
 int fits_url2path(char *inpath, char *outpath, int  *status);
 
@@ -57,7 +60,7 @@
 
 int fits_url2relurl(char *refURL, char *absURL, char *relURL, int *status);
 
-int fits_encode_url(char *inpath, char *outpath, int *status);
+int fits_encode_url(char *inpath, int maxlength, char *outpath, int *status);
 
 int fits_unencode_url(char *inpath, char *outpath, int *status);
 
diff -ur cfitsio3430/histo.c cfitsio3440/histo.c
--- cfitsio3430/histo.c	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/histo.c	2018-04-11 16:33:41.000000000 +0200
@@ -58,7 +58,7 @@
    most other reasonable combinations are supported.        
 */
     int ii, slen, defaulttype;
-    char *ptr, tmpname[30], *file_expr = NULL;
+    char *ptr, tmpname[FLEN_VALUE], *file_expr = NULL;
     double  dummy;
 
     if (*status > 0)
@@ -369,52 +369,78 @@
    the column name, histogram min and max values, and bin size.
 */
 {
-    int slen, isanumber;
-    char token[FLEN_VALUE];
+    int slen, isanumber=0;
+    char *token=0;
 
     if (*status > 0)
         return(*status);
 
-    slen = fits_get_token(ptr, " ,=:;", token, &isanumber); /* get 1st token */
+    slen = fits_get_token2(ptr, " ,=:;", &token, &isanumber, status); /* get 1st token */
 
-    if (slen == 0 && (**ptr == '\0' || **ptr == ',' || **ptr == ';') )
+    if ((*status) || (slen == 0 && (**ptr == '\0' || **ptr == ',' || **ptr == ';')) )
         return(*status);   /* a null range string */
-
+        
     if (!isanumber && **ptr != ':')
     {
         /* this looks like the column name */
-
-        if (token[0] == '#' && isdigit((int) token[1]) )
+        
+        /* Check for case where col name string is empty but '='
+           is still there (indicating a following specification string).
+           Musn't enter this block as token would not have been allocated. */
+        if (slen != 0 || (**ptr != '='))
         {
-            /* omit the leading '#' in the column number */
-            strcpy(colname, token+1);
-        }
-        else
-            strcpy(colname, token);
-
-        while (**ptr == ' ')  /* skip over blanks */
-             (*ptr)++;
+           if (strlen(token) > FLEN_VALUE-1)
+           {
+              ffpmsg("column name too long (ffbinr)");
+              free(token);
+              return(*status=PARSE_SYNTAX_ERR);
+           }
+           if (token[0] == '#' && isdigit((int) token[1]) )
+           {
+               /* omit the leading '#' in the column number */
+               strcpy(colname, token+1);
+           }
+           else
+               strcpy(colname, token);
+           free(token);
+           token=0;
+           while (**ptr == ' ')  /* skip over blanks */
+                (*ptr)++;
 
-        if (**ptr != '=')
-            return(*status);  /* reached the end */
+           if (**ptr != '=')
+               return(*status);  /* reached the end */
 
+        }
         (*ptr)++;   /* skip over the = sign */
 
         while (**ptr == ' ')  /* skip over blanks */
              (*ptr)++;
 
-        slen = fits_get_token(ptr, " ,:;", token, &isanumber); /* get token */
+        /* get specification info */
+        slen = fits_get_token2(ptr, " ,:;", &token, &isanumber, status);
+        if (*status)
+           return(*status);
     }
 
     if (**ptr != ':')
     {
-        /* this is the first token, and since it is not followed by */
-        /* a ':' this must be the binsize token */
+        /* This is the first token, and since it is not followed by 
+         a ':' this must be the binsize token. Or it could be empty
+         in which case none of the following operations will do anything */
         if (!isanumber)
+        {
+            if (strlen(token) > FLEN_VALUE-1)
+            {
+               ffpmsg("binname too long (ffbinr)");
+               free(token);
+               return(*status=PARSE_SYNTAX_ERR);
+            }
             strcpy(binname, token);
+        }
         else
             *binsizein =  strtod(token, NULL);
-
+        
+        free(token);
         return(*status);  /* reached the end */
     }
     else
@@ -423,37 +449,73 @@
         if (slen)
         {
             if (!isanumber)
+            {
+                if (strlen(token) > FLEN_VALUE-1)
+                {
+                   ffpmsg("minname too long (ffbinr)");
+                   free(token);
+                   return(*status=PARSE_SYNTAX_ERR);
+                }
                 strcpy(minname, token);
+            }
             else
                 *minin = strtod(token, NULL);
+            free(token);
+            token=0;
         }
     }
 
     (*ptr)++;  /* skip the colon between the min and max values */
-    slen = fits_get_token(ptr, " ,:;", token, &isanumber); /* get token */
+    slen = fits_get_token2(ptr, " ,:;", &token, &isanumber, status); /* get token */
+    if (*status)
+       return(*status);
 
     /* the token contains the max value */
     if (slen)
     {
         if (!isanumber)
+        {
+            if (strlen(token) > FLEN_VALUE-1)
+            {
+               ffpmsg("maxname too long (ffbinr)");
+               free(token);
+               return(*status=PARSE_SYNTAX_ERR);
+            }
             strcpy(maxname, token);
+        }
         else
             *maxin = strtod(token, NULL);
+        free(token);
+        token=0;
     }
 
     if (**ptr != ':')
+    {
+        free(token);
         return(*status);  /* reached the end; no binsize token */
+    }
 
     (*ptr)++;  /* skip the colon between the max and binsize values */
-    slen = fits_get_token(ptr, " ,:;", token, &isanumber); /* get token */
+    slen = fits_get_token2(ptr, " ,:;", &token, &isanumber, status); /* get token */
+    if (*status)
+       return(*status);
 
     /* the token contains the binsize value */
     if (slen)
     {
         if (!isanumber)
+        {
+            if (strlen(token) > FLEN_VALUE-1)
+            {
+               ffpmsg("binname too long (ffbinr)");
+               free(token);
+               return(*status=PARSE_SYNTAX_ERR);
+            }
             strcpy(binname, token);
+        }
         else
             *binsizein = strtod(token, NULL);
+        free(token);
     }
 
     return(*status);
@@ -935,7 +997,7 @@
               > 0)
       {
         strcpy(errmsg, "column for histogram axis doesn't exist: ");
-        strcat(errmsg, colname[ii]);
+        strncat(errmsg, colname[ii], FLEN_ERRMSG-strlen(errmsg)-1);
         ffpmsg(errmsg);
         return(*status);
       }
@@ -947,7 +1009,7 @@
       if (repeat > 1)
       {
         strcpy(errmsg, "Can't bin a vector column: ");
-        strcat(errmsg, colname[ii]);
+        strncat(errmsg, colname[ii],FLEN_ERRMSG-strlen(errmsg)-1);
         ffpmsg(errmsg);
         return(*status = BAD_DATATYPE);
       }
@@ -959,7 +1021,7 @@
       if (datatype < 0 || datatype == TSTRING)
       {
         strcpy(errmsg, "Inappropriate datatype; can't bin this column: ");
-        strcat(errmsg, colname[ii]);
+        strncat(errmsg, colname[ii],FLEN_ERRMSG-strlen(errmsg)-1);
         ffpmsg(errmsg);
         return(*status = BAD_DATATYPE);
       }
@@ -970,14 +1032,14 @@
       if (minin[ii] == DOUBLENULLVALUE)
       {
         ffkeyn("TLMIN", histData.hcolnum[ii], keyname, status);
-        if (ffgky(*fptr, TFLOAT, keyname, amin+ii, NULL, status) > 0)
+        if (ffgky(*fptr, TFLOAT, keyname, amin+ii, NULL, status) > 0)
         {
             /* use actual data minimum value for the histogram minimum */
             *status = 0;
             if (fits_get_col_minmax(*fptr, histData.hcolnum[ii], amin+ii, &datamax, status) > 0)
             {
                 strcpy(errmsg, "Error calculating datamin and datamax for column: ");
-                strcat(errmsg, colname[ii]);
+                strncat(errmsg, colname[ii],FLEN_ERRMSG-strlen(errmsg)-1);
                 ffpmsg(errmsg);
                 return(*status);
             }
@@ -1004,7 +1066,7 @@
              if (fits_get_col_minmax(*fptr, histData.hcolnum[ii], &datamin, &amax[ii], status) > 0)
              {
                  strcpy(errmsg, "Error calculating datamin and datamax for column: ");
-                 strcat(errmsg, colname[ii]);
+                 strncat(errmsg, colname[ii],FLEN_ERRMSG-strlen(errmsg)-1);
                  ffpmsg(errmsg);
                  return(*status);
              }
@@ -1543,7 +1646,7 @@
               > 0)
       {
           strcpy(errmsg, "column for histogram axis doesn't exist: ");
-          strcat(errmsg, colname[ii]);
+          strncat(errmsg, colname[ii],FLEN_ERRMSG-strlen(errmsg)-1);
           ffpmsg(errmsg);
           return(*status);
       }
@@ -1558,7 +1661,7 @@
       if (repeat > 1)
       {
         strcpy(errmsg, "Can't bin a vector column: ");
-        strcat(errmsg, colname[ii]);
+        strncat(errmsg, colname[ii],FLEN_ERRMSG-strlen(errmsg)-1);
         ffpmsg(errmsg);
         return(*status = BAD_DATATYPE);
       }
@@ -1570,7 +1673,7 @@
       if (datatype < 0 || datatype == TSTRING)
       {
         strcpy(errmsg, "Inappropriate datatype; can't bin this column: ");
-        strcat(errmsg, colname[ii]);
+        strncat(errmsg, colname[ii],FLEN_ERRMSG-strlen(errmsg)-1);
         ffpmsg(errmsg);
         return(*status = BAD_DATATYPE);
       }
@@ -1593,19 +1696,19 @@
 
       if (minin[ii] != DOUBLENULLVALUE)
       {
-        amin[ii] = (float) minin[ii];
+        amin[ii] = (float) minin[ii];
       }
       else
       {
         ffkeyn("TLMIN", colnum[ii], keyname, status);
-        if (ffgky(fptr, TFLOAT, keyname, amin+ii, NULL, status) > 0)
+        if (ffgky(fptr, TFLOAT, keyname, amin+ii, NULL, status) > 0)
         {
             /* use actual data minimum value for the histogram minimum */
             *status = 0;
             if (fits_get_col_minmax(fptr, colnum[ii], amin+ii, &datamax, status) > 0)
             {
                 strcpy(errmsg, "Error calculating datamin and datamax for column: ");
-                strcat(errmsg, colname[ii]);
+                strncat(errmsg, colname[ii],FLEN_ERRMSG-strlen(errmsg)-1);
                 ffpmsg(errmsg);
                 return(*status);
             }
@@ -1645,7 +1748,7 @@
              if (fits_get_col_minmax(fptr, colnum[ii], &datamin, &amax[ii], status) > 0)
              {
                  strcpy(errmsg, "Error calculating datamin and datamax for column: ");
-                 strcat(errmsg, colname[ii]);
+                 strncat(errmsg, colname[ii],FLEN_ERRMSG-strlen(errmsg)-1);
                  ffpmsg(errmsg);
                  return(*status);
              }
diff -ur cfitsio3430/imcompress.c cfitsio3440/imcompress.c
--- cfitsio3430/imcompress.c	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/imcompress.c	2018-04-11 16:33:41.000000000 +0200
@@ -162,8 +162,8 @@
 static int fits_unshuffle_2bytes(char *heap, LONGLONG length, int *status);
 
 static int fits_int_to_longlong_inplace(int *intarray, long length, int *status);
-static int fits_short_to_int_inplace(short *intarray, long length, int *status);
-static int fits_ushort_to_int_inplace(unsigned short *intarray, long length, int *status);
+static int fits_short_to_int_inplace(short *intarray, long length, int shift, int *status);
+static int fits_ushort_to_int_inplace(unsigned short *intarray, long length, int shift, int *status);
 static int fits_sbyte_to_int_inplace(signed char *intarray, long length, int *status);
 static int fits_ubyte_to_int_inplace(unsigned char *intarray, long length, int *status);
 
@@ -2252,7 +2252,7 @@
            } else {  /* just do the data type conversion to int */
                  /* have to convert sbuff to an I*4 array, in place */
                  /* sbuff must have been allocated large enough to do this */
-                 fits_short_to_int_inplace(sbuff, tilelen, status);
+                 fits_short_to_int_inplace(sbuff, tilelen, 0, status);
            }
        } else {
            /* have to convert to int if using PLIO */
@@ -2273,10 +2273,10 @@
                     else
                        idata[ii] = (int) sbuff[ii] + 32768;
                }
-             } else {  /* just do the data type conversion to int */
+             } else {  
                  /* have to convert sbuff to an I*4 array, in place */
                  /* sbuff must have been allocated large enough to do this */
-                 fits_short_to_int_inplace(sbuff, tilelen, status);
+                 fits_short_to_int_inplace(sbuff, tilelen, 32768, status);
              }
            } else {
 	     /* This is not an unsigned 16-bit integer array, so process normally */
@@ -2292,7 +2292,7 @@
              } else {  /* just do the data type conversion to int */
                  /* have to convert sbuff to an I*4 array, in place */
                  /* sbuff must have been allocated large enough to do this */
-                 fits_short_to_int_inplace(sbuff, tilelen, status);
+                 fits_short_to_int_inplace(sbuff, tilelen, 0, status);
              }
            }
         }
@@ -2373,9 +2373,15 @@
 		       idata[ii] = ((int) usbuff[ii]) - 32768;
                }
            } else {  /* just do the data type conversion to int */
-                 /* have to convert usbuff to an I*4 array, in place */
-                 /* usbuff must have been allocated large enough to do this */
-                 fits_ushort_to_int_inplace(usbuff, tilelen, status);
+               /* for HCOMPRESS we need to simply subtract 32768 */
+               /* for PLIO, have to convert usbuff to an I*4 array, in place */
+               /* usbuff must have been allocated large enough to do this */
+
+               if ((outfptr->Fptr)->compress_type == HCOMPRESS_1) {
+                    fits_ushort_to_int_inplace(usbuff, tilelen, -32768, status);
+               } else {
+                    fits_ushort_to_int_inplace(usbuff, tilelen, 0, status);
+               }
            }
         }
 
@@ -8397,7 +8403,7 @@
 		    cratio[ii] = uncompressed_size / compressed_size;
 
 		snprintf(tempstring,FLEN_VALUE," r=%6.2f",cratio[ii]);
-		strcat(results[ii],tempstring);
+		strncat(results[ii],tempstring, 29-strlen(results[ii]));
 
 		/* now we just have to compress the array of descriptors (both input and output) */
 		/* and write them to the output table. */
@@ -8524,7 +8530,7 @@
 	       cratio[ii] = (float) datasize / (float) dlen;  /* compression ratio of the column */
 
 	    snprintf(tempstring,FLEN_VALUE," r=%6.2f",cratio[ii]);
-	    strcat(results[ii],tempstring);
+	    strncat(results[ii],tempstring,29-strlen(results[ii]));
  
           }  /* end of not a virtual column */
         }  /* end of loop over columns */
@@ -9508,7 +9514,7 @@
     return(*status);
 }
 /*--------------------------------------------------------------------------*/
-static int fits_short_to_int_inplace(short *shortarray, long length, int *status)
+static int fits_short_to_int_inplace(short *shortarray, long length, int shift, int *status)
 
 /* convert the input array of 16-bit integers into an array of 32-bit integers,
 in place. This will overwrite the input array with the new longer array starting
@@ -9549,7 +9555,7 @@
     
 	/* do datatype conversion into temp array */
         for (ii = 0; ii < ntodo; ii++) { 
-	    intarray[ii] = shortarray[ii + firstelem];
+	    intarray[ii] = (int)(shortarray[ii + firstelem]) + shift;
         }
 
         /* copy temp array back to alias */
@@ -9572,7 +9578,7 @@
 }
 /*--------------------------------------------------------------------------*/
 static int fits_ushort_to_int_inplace(unsigned short *ushortarray, long length, 
-                                      int *status)
+                                      int shift, int *status)
 
 /* convert the input array of 16-bit unsigned integers into an array of 32-bit integers,
 in place. This will overwrite the input array with the new longer array starting
@@ -9613,7 +9619,7 @@
     
 	/* do datatype conversion into temp array */
         for (ii = 0; ii < ntodo; ii++) { 
-	    intarray[ii] = ushortarray[ii + firstelem];
+	    intarray[ii] = (int)(ushortarray[ii + firstelem]) + shift;
         }
 
         /* copy temp array back to alias */
diff -ur cfitsio3430/iraffits.c cfitsio3440/iraffits.c
--- cfitsio3430/iraffits.c	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/iraffits.c	2018-04-11 16:33:41.000000000 +0200
@@ -1329,6 +1329,8 @@
 /* Translate value from ASCII to binary */
 	if (value != NULL) {
 	    minint = -MAXINT - 1;
+            if (strlen(value) > 29)
+               return(0);
 	    strcpy (val, value);
 	    dval = atof (val);
 	    if (dval+0.001 > MAXINT)
@@ -1372,10 +1374,13 @@
 	    lval = strlen (value);
 	    if (lval < lstr)
 		strcpy (str, value);
-	    else if (lstr > 1)
+	    else if (lstr > 1) {
 		strncpy (str, value, lstr-1);
-	    else
+                str[lstr-1]=0;
+            }
+	    else {
 		str[0] = value[0];
+            }
 	    return (1);
 	    }
 	else
@@ -1422,6 +1427,7 @@
 
 /* Find length of variable name */
 	strncpy (keyword,keyword0, sizeof(keyword)-1);
+        keyword[80]=0;
 	brack1 = strsrch (keyword,lbracket);
 	if (brack1 == NULL)
 	    brack1 = strsrch (keyword,comma);
--- cfitsio3430/modkey.c	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/modkey.c	2018-04-11 16:33:42.000000000 +0200
@@ -754,6 +754,11 @@
     contin = 0;
     while (remain > 0)
     {
+        if (nchar > FLEN_VALUE-1)
+        {
+           ffpmsg("longstr keyword value is too long (ffmkls)");
+           return (*status=BAD_KEYCHAR);
+        }
         strncpy(tstring, &value[next], nchar); /* copy string to temp buff */
         tstring[nchar] = '\0';
         ffs2c(tstring, valstring, status);  /* put quotes around the string */
@@ -984,9 +989,19 @@
 
     strcpy(valstring, "(" );
     ffr2f(value[0], decim, tmpstring, status); /* convert to string */
+    if (strlen(tmpstring)+3 > FLEN_VALUE-1)
+    {
+       ffpmsg("complex key value too long (ffmkfc)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ", ");
     ffr2f(value[1], decim, tmpstring, status); /* convert to string */
+    if (strlen(valstring) + strlen(tmpstring)+1 > FLEN_VALUE-1)
+    {
+       ffpmsg("complex key value too long (ffmkfc)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ")");
 
@@ -1019,9 +1034,19 @@
 
     strcpy(valstring, "(" );
     ffr2e(value[0], decim, tmpstring, status); /* convert to string */
+    if (strlen(tmpstring)+3 > FLEN_VALUE-1)
+    {
+       ffpmsg("complex key value too long (ffmkyc)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ", ");
     ffr2e(value[1], decim, tmpstring, status); /* convert to string */
+    if (strlen(valstring) + strlen(tmpstring)+1 > FLEN_VALUE-1)
+    {
+       ffpmsg("complex key value too long (ffmkyc)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ")");
 
@@ -1054,9 +1079,19 @@
 
     strcpy(valstring, "(" );
     ffd2f(value[0], decim, tmpstring, status); /* convert to string */
+    if (strlen(tmpstring)+3 > FLEN_VALUE-1)
+    {
+       ffpmsg("complex key value too long (ffmkfm)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ", ");
     ffd2f(value[1], decim, tmpstring, status); /* convert to string */
+    if (strlen(valstring) + strlen(tmpstring)+1 > FLEN_VALUE-1)
+    {
+       ffpmsg("complex key value too long (ffmkfm)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ")");
 
@@ -1089,9 +1124,19 @@
 
     strcpy(valstring, "(" );
     ffd2e(value[0], decim, tmpstring, status); /* convert to string */
+    if (strlen(tmpstring)+3 > FLEN_VALUE-1)
+    {
+       ffpmsg("complex key value too long (ffmkym)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ", ");
     ffd2e(value[1], decim, tmpstring, status); /* convert to string */
+    if (strlen(valstring) + strlen(tmpstring)+1 > FLEN_VALUE-1)
+    {
+       ffpmsg("complex key value too long (ffmkym)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ")");
 
@@ -1208,6 +1253,11 @@
     contin = 0;
     while (remain > 0)
     {
+        if (nchar > FLEN_VALUE-1)
+        {
+           ffpmsg("longstr keyword value is too long (ffikls)");
+           return (*status=BAD_KEYCHAR);
+        }
         strncpy(tstring, &value[next], nchar); /* copy string to temp buff */
         tstring[nchar] = '\0';
         ffs2c(tstring, valstring, status);  /* put quotes around the string */
@@ -1379,9 +1429,19 @@
 
     strcpy(valstring, "(" );
     ffr2f(value[0], decim, tmpstring, status); /* convert to string */
+    if (strlen(tmpstring)+3 > FLEN_VALUE-1)
+    {
+       ffpmsg("complex key value too long (ffikfc)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ", ");
     ffr2f(value[1], decim, tmpstring, status); /* convert to string */
+    if (strlen(valstring) + strlen(tmpstring)+1 > FLEN_VALUE-1)
+    {
+       ffpmsg("complex key value too long (ffikfc)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ")");
 
@@ -1406,9 +1466,19 @@
 
     strcpy(valstring, "(" );
     ffr2e(value[0], decim, tmpstring, status); /* convert to string */
+    if (strlen(tmpstring)+3 > FLEN_VALUE-1)
+    {
+       ffpmsg("complex key value too long (ffikyc)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ", ");
     ffr2e(value[1], decim, tmpstring, status); /* convert to string */
+    if (strlen(valstring) + strlen(tmpstring)+1 > FLEN_VALUE-1)
+    {
+       ffpmsg("complex key value too long (ffikyc)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ")");
 
@@ -1434,9 +1504,19 @@
 
     strcpy(valstring, "(" );
     ffd2f(value[0], decim, tmpstring, status); /* convert to string */
+    if (strlen(tmpstring)+3 > FLEN_VALUE-1)
+    {
+       ffpmsg("complex key value too long (ffikfm)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ", ");
     ffd2f(value[1], decim, tmpstring, status); /* convert to string */
+    if (strlen(valstring) + strlen(tmpstring)+1 > FLEN_VALUE-1)
+    {
+       ffpmsg("complex key value too long (ffikfm)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ")");
 
@@ -1461,9 +1541,19 @@
 
     strcpy(valstring, "(" );
     ffd2e(value[0], decim, tmpstring, status); /* convert to string */
+    if (strlen(tmpstring)+3 > FLEN_VALUE-1)
+    {
+       ffpmsg("complex key value too long (ffikym)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ", ");
     ffd2e(value[1], decim, tmpstring, status); /* convert to string */
+    if (strlen(valstring) + strlen(tmpstring)+1 > FLEN_VALUE-1)
+    {
+       ffpmsg("complex key value too long (ffikym)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ")");
 
@@ -1531,6 +1621,11 @@
     keylength = strcspn(buff2, "=");
     if (keylength == 80) keylength = 8;
     
+    /* test for the common commentary keywords which by definition have 8-char names */
+    if ( !fits_strncasecmp( "COMMENT ", buff2, 8) || !fits_strncasecmp( "HISTORY ", buff2, 8) ||
+         !fits_strncasecmp( "        ", buff2, 8) || !fits_strncasecmp( "CONTINUE", buff2, 8) )
+	 keylength = 8;
+
     for (ii=0; ii < keylength; ii++)       /* make sure keyword name is uppercase */
         buff2[ii] = toupper(buff2[ii]);
 
diff -ur cfitsio3430/putcol.c cfitsio3440/putcol.c
--- cfitsio3430/putcol.c	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/putcol.c	2018-04-11 16:33:42.000000000 +0200
@@ -855,7 +855,8 @@
 */
 {
     col->fptr = fptr;
-    strcpy(col->colname, colname);
+    strncpy(col->colname, colname,69);
+    col->colname[69]=0;
     col->colnum = 0;  /* set column number undefined since name is given */
     col->datatype = datatype;
     col->iotype = iotype;
@@ -894,7 +895,8 @@
   set iterator column parameter
 */
 {
-    strcpy(col->colname, colname);
+    strncpy(col->colname, colname,69);
+    col->colname[69]=0;
     col->colnum = 0;  /* set column number undefined since name is given */
     return(0);
 }
diff -ur cfitsio3430/putkey.c cfitsio3440/putkey.c
--- cfitsio3430/putkey.c	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/putkey.c	2018-04-11 16:33:42.000000000 +0200
@@ -724,9 +724,19 @@
 
     strcpy(valstring, "(" );
     ffr2e(value[0], decim, tmpstring, status); /* convert to string */
+    if (strlen(valstring)+strlen(tmpstring)+2 > FLEN_VALUE-1)
+    {
+       ffpmsg("Error converting complex to string (ffpkyc)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ", ");
     ffr2e(value[1], decim, tmpstring, status); /* convert to string */
+    if (strlen(valstring)+strlen(tmpstring)+1 > FLEN_VALUE-1)
+    {
+       ffpmsg("Error converting complex to string (ffpkyc)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ")");
 
@@ -755,9 +765,19 @@
 
     strcpy(valstring, "(" );
     ffd2e(value[0], decim, tmpstring, status); /* convert to string */
+    if (strlen(valstring)+strlen(tmpstring)+2 > FLEN_VALUE-1)
+    {
+       ffpmsg("Error converting complex to string (ffpkym)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ", ");
     ffd2e(value[1], decim, tmpstring, status); /* convert to string */
+    if (strlen(valstring)+strlen(tmpstring)+1 > FLEN_VALUE-1)
+    {
+       ffpmsg("Error converting complex to string (ffpkym)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ")");
 
@@ -786,9 +806,19 @@
 
     strcpy(valstring, "(" );
     ffr2f(value[0], decim, tmpstring, status); /* convert to string */
+    if (strlen(valstring)+strlen(tmpstring)+2 > FLEN_VALUE-1)
+    {
+       ffpmsg("Error converting complex to string (ffpkfc)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ", ");
     ffr2f(value[1], decim, tmpstring, status); /* convert to string */
+    if (strlen(valstring)+strlen(tmpstring)+1 > FLEN_VALUE-1)
+    {
+       ffpmsg("Error converting complex to string (ffpkfc)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ")");
 
@@ -817,9 +847,19 @@
 
     strcpy(valstring, "(" );
     ffd2f(value[0], decim, tmpstring, status); /* convert to string */
+    if (strlen(valstring)+strlen(tmpstring)+2 > FLEN_VALUE-1)
+    {
+       ffpmsg("Error converting complex to string (ffpkfm)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ", ");
     ffd2f(value[1], decim, tmpstring, status); /* convert to string */
+    if (strlen(valstring)+strlen(tmpstring)+1 > FLEN_VALUE-1)
+    {
+       ffpmsg("Error converting complex to string (ffpkfm)");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, tmpstring);
     strcat(valstring, ")");
 
@@ -858,6 +898,11 @@
     ffd2f(fraction, 16, fstring, status);  /* convert to 16 decimal string */
 
     cptr = strchr(fstring, '.');    /* find the decimal point */
+    if (strlen(valstring)+strlen(cptr) > FLEN_VALUE-1)
+    {
+       ffpmsg("converted numerical string too long");
+       return(*status=BAD_F2C);
+    }
     strcat(valstring, cptr);    /* append the fraction to the integer */
 
     ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
@@ -1990,6 +2035,12 @@
         }
 
         snprintf(value, 80,"%ld", naxes[ii]);
+        /* This will either be followed by a ',' or ')'. */
+        if (strlen(tdimstr)+strlen(value)+1 > FLEN_VALUE-1)
+        {
+            ffpmsg("TDIM string too long (ffptdm)");
+            return(*status = BAD_TDIM);
+        }
         strcat(tdimstr, value);     /* append the axis size */
 
         totalpix *= naxes[ii];
@@ -2087,7 +2138,12 @@
         /* sprintf is platform dependent ( %lld, %ld, %I64d )            */
 
         snprintf(value, 80, "%.0f", (double) naxes[ii]);
-
+        
+        if (strlen(tdimstr)+strlen(value)+1 > FLEN_VALUE-1)
+        {
+            ffpmsg("TDIM string too long (ffptdmll)");
+            return(*status = BAD_TDIM);
+        }
         strcat(tdimstr, value);     /* append the axis size */
 
         totalpix *= naxes[ii];
@@ -2464,6 +2520,12 @@
         ffkeyn("TBCOL", ii + 1, name, status);
         ffpkyj(fptr, name, tbcol[ii], comm, status);
 
+        if (strlen(tform[ii]) > 29)
+        {
+          ffpmsg("Error: ASCII table TFORM code is too long (ffphtb)");
+          *status = BAD_TFORM;
+          break;
+        }
         strcpy(tfmt, tform[ii]);  /* required TFORMn keyword */
         ffupch(tfmt);
         ffkeyn("TFORM", ii + 1, name, status);
@@ -2582,6 +2644,12 @@
           ffpkys(fptr, name, ttype[ii], comm, status);
         }
 
+        if (strlen(tform[ii]) > 29)
+        {
+          ffpmsg("Error: BIN table TFORM code is too long (ffphbn)");
+          *status = BAD_TFORM;
+          break;
+        }
         strcpy(tfmt, tform[ii]);  /* required TFORMn keyword */
         ffupch(tfmt);
 
@@ -2915,7 +2983,7 @@
         return(*status = BAD_DECIM);
     }
 
-    if (sprintf(cval, "%.*f", decim, fval) < 0)
+    if (snprintf(cval, FLEN_VALUE,"%.*f", decim, fval) < 0)
     {
         ffpmsg("Error in ffr2f converting float to string");
         *status = BAD_F2C;
@@ -2951,7 +3019,7 @@
 
     if (decim < 0)
     {   /* use G format if decim is negative */
-        if ( sprintf(cval, "%.*G", -decim, fval) < 0)
+        if ( snprintf(cval, FLEN_VALUE,"%.*G", -decim, fval) < 0)
         {
             ffpmsg("Error in ffr2e converting float to string");
             *status = BAD_F2C;
@@ -2962,7 +3030,7 @@
             if ( !strchr(cval, '.') && strchr(cval,'E') )
             {
                 /* reformat value with a decimal point and single zero */
-                if ( sprintf(cval, "%.1E", fval) < 0)
+                if ( snprintf(cval, FLEN_VALUE,"%.1E", fval) < 0)
                 {
                     ffpmsg("Error in ffr2e converting float to string");
                     *status = BAD_F2C;
@@ -2974,7 +3042,7 @@
     }
     else
     {
-        if ( sprintf(cval, "%.*E", decim, fval) < 0)
+        if ( snprintf(cval, FLEN_VALUE,"%.*E", decim, fval) < 0)
         {
             ffpmsg("Error in ffr2e converting float to string");
             *status = BAD_F2C;
@@ -2992,7 +3060,7 @@
             ffpmsg("Error in ffr2e: float value is a NaN or INDEF");
             *status = BAD_F2C;
         }
-        else if ( !strchr(cval, '.') && !strchr(cval,'E') )
+        else if ( !strchr(cval, '.') && !strchr(cval,'E') && strlen(cval) < FLEN_VALUE-1 )
         {
             /* add decimal point if necessary to distinquish from integer */
             strcat(cval, ".");
@@ -3023,7 +3091,7 @@
         return(*status = BAD_DECIM);
     }
 
-    if (sprintf(cval, "%.*f", decim, dval) < 0)
+    if (snprintf(cval, FLEN_VALUE,"%.*f", decim, dval) < 0)
     {
         ffpmsg("Error in ffd2f converting double to string");
         *status = BAD_F2C;
@@ -3059,7 +3127,7 @@
 
     if (decim < 0)
     {   /* use G format if decim is negative */
-        if ( sprintf(cval, "%.*G", -decim, dval) < 0)
+        if ( snprintf(cval, FLEN_VALUE,"%.*G", -decim, dval) < 0)
         {
             ffpmsg("Error in ffd2e converting float to string");
             *status = BAD_F2C;
@@ -3070,7 +3138,7 @@
             if ( !strchr(cval, '.') && strchr(cval,'E') )
             {
                 /* reformat value with a decimal point and single zero */
-                if ( sprintf(cval, "%.1E", dval) < 0)
+                if ( snprintf(cval, FLEN_VALUE,"%.1E", dval) < 0)
                 {
                     ffpmsg("Error in ffd2e converting float to string");
                     *status = BAD_F2C;
@@ -3082,7 +3150,7 @@
     }
     else
     {
-        if ( sprintf(cval, "%.*E", decim, dval) < 0)
+        if ( snprintf(cval, FLEN_VALUE,"%.*E", decim, dval) < 0)
         {
             ffpmsg("Error in ffd2e converting float to string");
             *status = BAD_F2C;
@@ -3100,7 +3168,7 @@
             ffpmsg("Error in ffd2e: double value is a NaN or INDEF");
             *status = BAD_F2C;
         }
-        else if ( !strchr(cval, '.') && !strchr(cval,'E') )
+        else if ( !strchr(cval, '.') && !strchr(cval,'E') && strlen(cval) < FLEN_VALUE-1)
         {
             /* add decimal point if necessary to distinquish from integer */
             strcat(cval, ".");
diff -ur cfitsio3430/windumpexts.c cfitsio3440/windumpexts.c
--- cfitsio3430/windumpexts.c	2018-03-01 17:28:51.000000000 +0100
+++ cfitsio3440/windumpexts.c	2018-04-11 16:33:42.000000000 +0200
@@ -232,7 +232,8 @@
 		    symbol[8] = 0;
 		} else {
 		    s = stringTable + pSymbolTable->N.Name.Long;
-		    strcpy(symbol, s);
+		    strncpy(symbol, s, 1023);
+                    symbol[1023]=0;
 		}
 		s = symbol;
 		f = strchr(s, '@');
@@ -485,7 +486,8 @@
 	    }
 	    pos = 0;
 	    for (i = 0; i < arg; i++) {
-		strcpy(&cmdline[pos], argv[i]);
+		strncpy(&cmdline[pos], argv[i], 9999-pos);
+                cmdline[9999]=0;
 		pos += strlen(&cmdline[pos]) + 1;
 		fargv[i] = argv[i];
 	    }