From 26f431c9443f411c8c00f005600910c167a30517 Mon Sep 17 00:00:00 2001
From: Joerg Wunsch <j@uriah.heep.sax.de>
Date: Sat, 23 Jul 2022 10:26:17 +0200
Subject: [PATCH 1/3] Handle invalid -U file format specifiers for input

The file format specifiers 'h', 'd', 'o', and 'b' are only valid for
outputting data. Reject them with a proper error message when
attempting to use them for input.
---
 src/update.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/src/update.c b/src/update.c
index d3c208fc..8642f39d 100644
--- a/src/update.c
+++ b/src/update.c
@@ -278,6 +278,34 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
      * write the selected device memory using data from a file; first
      * read the data from the specified file
      */
+    const char *name = 0;
+    switch (upd->format) {
+    case FMT_HEX:
+      name = "hex";
+      break;
+
+    case FMT_DEC:
+      name = "decimal";
+      break;
+
+    case FMT_OCT:
+      name = "octal";
+      break;
+
+    case FMT_BIN:
+      name = "binary";
+      break;
+
+    default:
+      // no action needed
+      break;
+    }
+    if (name != 0) {
+      avrdude_message(MSG_INFO,
+                      "%s: Invalid file format '%s' for input\n",
+                      progname, name, upd->filename);
+      return -1;
+    }
     if (quell_progress < 2) {
       avrdude_message(MSG_INFO, "%s: reading input file \"%s\"\n",
                       progname,

From ce1ae41dd68c07469a7f3d7421c758c95bde0903 Mon Sep 17 00:00:00 2001
From: Joerg Wunsch <j@uriah.heep.sax.de>
Date: Sat, 23 Jul 2022 16:30:38 +0200
Subject: [PATCH 2/3] Document that 'h', 'o', and 'd' file formats are
 output-only.

---
 src/avrdude.1        | 3 +++
 src/doc/avrdude.texi | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/src/avrdude.1 b/src/avrdude.1
index b312fff5..9f7eacde 100644
--- a/src/avrdude.1
+++ b/src/avrdude.1
@@ -733,14 +733,17 @@ fuse bit settings.
 hexadecimal; each value will get the string
 .Em 0x
 prepended.
+Only valid on output.
 .It Ar o
 octal; each value will get a
 .Em 0
 prepended unless it is less than 8 in which case it gets no prefix.
+Only valid on output.
 .It Ar b
 binary; each value will get the string
 .Em 0b
 prepended.
+Only valid on output.
 .El
 .Pp
 The default is to use auto detection for input files, and raw binary
diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi
index 83b6fb3f..24a14253 100644
--- a/src/doc/avrdude.texi
+++ b/src/doc/avrdude.texi
@@ -802,13 +802,16 @@ fuse bit settings.
 
 @item h
 hexadecimal; each value will get the string @emph{0x} prepended.
+Only valid on output.
 
 @item o
 octal; each value will get a @emph{0}
 prepended unless it is less than 8 in which case it gets no prefix.
+Only valid on output.
 
 @item b
 binary; each value will get the string @emph{0b} prepended.
+Only valid on output.
 
 @end table
 

From cc93bd2c8341f20abe2acdeabd86dea88b5169f3 Mon Sep 17 00:00:00 2001
From: Joerg Wunsch <j@uriah.heep.sax.de>
Date: Sat, 23 Jul 2022 22:47:38 +0200
Subject: [PATCH 3/3] Move the error handling for invalid file formats to
 fileio.c

The checks used to be in update.c, but as they are related to
the intended file operation, they are better placed in fileio.c.

The checks affected are to refuse 'm' on output (file write),
and 'd', 'h', 'o', and 'b' formats on input (file read).
---
 src/fileio.c | 19 +++++++++++++++++++
 src/update.c | 34 ----------------------------------
 2 files changed, 19 insertions(+), 34 deletions(-)

diff --git a/src/fileio.c b/src/fileio.c
index 1c81682d..080f69ba 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -1135,6 +1135,13 @@ static int fileio_imm(struct fioparms * fio,
         rc = loc;
       }
       break;
+
+    case FIO_WRITE:
+      avrdude_message(MSG_INFO,
+                      "%s: Invalid file format 'immediate' for output\n",
+                      progname);
+      return -1;
+
     default:
       avrdude_message(MSG_INFO, "%s: fileio: invalid operation=%d\n",
               progname, fio->op);
@@ -1248,27 +1255,32 @@ static int fileio_num(struct fioparms * fio,
 	       FILEFMT fmt)
 {
   const char *prefix;
+  const char *name;
   char cbuf[20];
   int base, i, num;
 
   switch (fmt) {
     case FMT_HEX:
+      name = "hex";
       prefix = "0x";
       base = 16;
       break;
 
     default:
     case FMT_DEC:
+      name = "decimal";
       prefix = "";
       base = 10;
       break;
 
     case FMT_OCT:
+      name = "octal";
       prefix = "0";
       base = 8;
       break;
 
     case FMT_BIN:
+      name = "binary";
       prefix = "0b";
       base = 2;
       break;
@@ -1278,6 +1290,13 @@ static int fileio_num(struct fioparms * fio,
   switch (fio->op) {
     case FIO_WRITE:
       break;
+
+    case FIO_READ:
+      avrdude_message(MSG_INFO,
+                      "%s: Invalid file format '%s' for input\n",
+                      progname, name);
+      return -1;
+
     default:
       avrdude_message(MSG_INFO, "%s: fileio: invalid operation=%d\n",
               progname, fio->op);
diff --git a/src/update.c b/src/update.c
index 8642f39d..29132724 100644
--- a/src/update.c
+++ b/src/update.c
@@ -238,12 +238,6 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
     /*
      * read out the specified device memory and write it to a file
      */
-    if (upd->format == FMT_IMM) {
-      avrdude_message(MSG_INFO,
-                      "%s: Invalid file format 'immediate' for output\n",
-                      progname, upd->filename);
-      return -1;
-    }
     if (quell_progress < 2) {
       avrdude_message(MSG_INFO, "%s: reading %s%s memory:\n",
             progname, mem->desc, alias_mem_desc);
@@ -278,34 +272,6 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
      * write the selected device memory using data from a file; first
      * read the data from the specified file
      */
-    const char *name = 0;
-    switch (upd->format) {
-    case FMT_HEX:
-      name = "hex";
-      break;
-
-    case FMT_DEC:
-      name = "decimal";
-      break;
-
-    case FMT_OCT:
-      name = "octal";
-      break;
-
-    case FMT_BIN:
-      name = "binary";
-      break;
-
-    default:
-      // no action needed
-      break;
-    }
-    if (name != 0) {
-      avrdude_message(MSG_INFO,
-                      "%s: Invalid file format '%s' for input\n",
-                      progname, name, upd->filename);
-      return -1;
-    }
     if (quell_progress < 2) {
       avrdude_message(MSG_INFO, "%s: reading input file \"%s\"\n",
                       progname,