diff --git a/iconv/Makefile b/iconv/Makefile
index b0fa550141..29e4f280ec 100644
--- a/iconv/Makefile
+++ b/iconv/Makefile
@@ -61,6 +61,10 @@ test-srcs := \
 	tst-translit-mchar \
 	# test-srcs
 
+tests-internal = \
+	tst-iconv-sticky-input-error \
+	# tests-internal
+
 others		= iconv_prog iconvconfig
 install-others-programs	= $(inst_bindir)/iconv
 install-sbin	= iconvconfig
diff --git a/iconv/gconv_int.h b/iconv/gconv_int.h
index 9fece3ea14..cd452d94cc 100644
--- a/iconv/gconv_int.h
+++ b/iconv/gconv_int.h
@@ -331,4 +331,34 @@ extern wint_t __gconv_btwoc_ascii (struct __gconv_step *step, unsigned char c);
 
 __END_DECLS
 
+/* Internal extensions for <gconv.h>.  */
+
+/* Internal flags for __flags in struct __gconv_step_data.  Overlaps
+   with flags for __gconv_open.  */
+enum
+  {
+    /* The conversion encountered an illegal input character at one
+       point.  */
+    __GCONV_ENCOUNTERED_ILLEGAL_INPUT = 1U << 30,
+  };
+
+/* Mark *STEP_DATA as having seen illegal input, and return
+   __GCONV_ILLEGAL_INPUT.  */
+static inline int
+__gconv_mark_illegal_input (struct __gconv_step_data *step_data)
+{
+  step_data->__flags |= __GCONV_ENCOUNTERED_ILLEGAL_INPUT;
+  return __GCONV_ILLEGAL_INPUT;
+}
+
+/* Returns true if any of the conversion steps encountered illegal input.  */
+static _Bool __attribute__ ((unused))
+__gconv_has_illegal_input (__gconv_t cd)
+{
+  for (size_t i = 0; i < cd->__nsteps; ++i)
+    if (cd->__data[i].__flags & __GCONV_ENCOUNTERED_ILLEGAL_INPUT)
+      return true;
+  return false;
+}
+
 #endif /* gconv_int.h */
diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c
index 257be2f8ff..f22002cf81 100644
--- a/iconv/gconv_simple.c
+++ b/iconv/gconv_simple.c
@@ -207,7 +207,7 @@ ucs4_internal_loop (struct __gconv_step *step,
 	     UCS4 does not allow such values.  */
 	  if (irreversible == NULL)
 	    /* We are transliterating, don't try to correct anything.  */
-	    return __GCONV_ILLEGAL_INPUT;
+	    return __gconv_mark_illegal_input (step_data);
 
 	  if (flags & __GCONV_IGNORE_ERRORS)
 	    {
@@ -218,7 +218,7 @@ ucs4_internal_loop (struct __gconv_step *step,
 
 	  *inptrp = inptr;
 	  *outptrp = outptr;
-	  return __GCONV_ILLEGAL_INPUT;
+	  return __gconv_mark_illegal_input (step_data);
 	}
 
       put32 (outptr, inval);
@@ -276,7 +276,7 @@ ucs4_internal_loop_single (struct __gconv_step *step,
       if (!(flags & __GCONV_IGNORE_ERRORS))
 	{
 	  *inptrp -= cnt - (state->__count & 7);
-	  return __GCONV_ILLEGAL_INPUT;
+	  return __gconv_mark_illegal_input (step_data);
 	}
     }
   else
@@ -453,7 +453,7 @@ ucs4le_internal_loop (struct __gconv_step *step,
 	     UCS4 does not allow such values.  */
 	  if (irreversible == NULL)
 	    /* We are transliterating, don't try to correct anything.  */
-	    return __GCONV_ILLEGAL_INPUT;
+	    return __gconv_mark_illegal_input (step_data);
 
 	  if (flags & __GCONV_IGNORE_ERRORS)
 	    {
@@ -464,7 +464,7 @@ ucs4le_internal_loop (struct __gconv_step *step,
 
 	  *inptrp = inptr;
 	  *outptrp = outptr;
-	  return __GCONV_ILLEGAL_INPUT;
+	  return __gconv_mark_illegal_input (step_data);
 	}
 
       put32 (outptr, inval);
@@ -523,7 +523,7 @@ ucs4le_internal_loop_single (struct __gconv_step *step,
 	 represent the result.  This is a genuine bug in the input since
 	 UCS4 does not allow such values.  */
       if (!(flags & __GCONV_IGNORE_ERRORS))
-	return __GCONV_ILLEGAL_INPUT;
+	return __gconv_mark_illegal_input (step_data);
     }
   else
     {
@@ -969,7 +969,7 @@ ucs4le_internal_loop_single (struct __gconv_step *step,
 	   surrogates pass through, attackers could make a security	      \
 	   hole exploit by synthesizing any desired plane 1-16		      \
 	   character.  */						      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
+	result = __gconv_mark_illegal_input (step_data);		      \
 	if (! ignore_errors_p ())					      \
 	  break;							      \
 	inptr += 4;							      \
@@ -1012,7 +1012,7 @@ ucs4le_internal_loop_single (struct __gconv_step *step,
 	   them.  (Catching this here is not security relevant.)  */	      \
 	if (! ignore_errors_p ())					      \
 	  {								      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    result = __gconv_mark_illegal_input (step_data);		      \
 	    break;							      \
 	  }								      \
 	inptr += 2;							      \
@@ -1061,7 +1061,7 @@ ucs4le_internal_loop_single (struct __gconv_step *step,
 	   character.  */						      \
 	if (! ignore_errors_p ())					      \
 	  {								      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    result = __gconv_mark_illegal_input (step_data);		      \
 	    break;							      \
 	  }								      \
 	inptr += 4;							      \
diff --git a/iconv/gconv_trans.c b/iconv/gconv_trans.c
index 44f0fd849a..54c4f3a100 100644
--- a/iconv/gconv_trans.c
+++ b/iconv/gconv_trans.c
@@ -232,6 +232,6 @@ __gconv_transliterate (struct __gconv_step *step,
     }
 
   /* Haven't found a match.  */
-  return __GCONV_ILLEGAL_INPUT;
+  return __gconv_mark_illegal_input (step_data);
 }
 libc_hidden_def (__gconv_transliterate)
diff --git a/iconv/iconv_prog.c b/iconv/iconv_prog.c
index 88a928557e..5fe4fe7a6c 100644
--- a/iconv/iconv_prog.c
+++ b/iconv/iconv_prog.c
@@ -291,6 +291,11 @@ conversions from `%s' and to `%s' are not supported"),
 	  }
 	while (++remaining < argc);
 
+      /* Ensure that iconv -c still exits with failure if iconv (the
+	 function) has failed with E2BIG instead of EILSEQ.  */
+      if (__gconv_has_illegal_input (cd))
+	status = EXIT_FAILURE;
+
       /* Close the output file now.  */
       if (output != NULL && fclose (output))
 	error (EXIT_FAILURE, errno, _("error while closing output file"));
diff --git a/iconv/loop.c b/iconv/loop.c
index 5340dafc70..199fb28326 100644
--- a/iconv/loop.c
+++ b/iconv/loop.c
@@ -123,8 +123,7 @@
    `continue' must reach certain points.  */
 #define STANDARD_FROM_LOOP_ERR_HANDLER(Incr) \
   {									      \
-    result = __GCONV_ILLEGAL_INPUT;					      \
-									      \
+    result = __gconv_mark_illegal_input (step_data);			      \
     if (! ignore_errors_p ())						      \
       break;								      \
 									      \
@@ -142,7 +141,7 @@
    points.  */
 #define STANDARD_TO_LOOP_ERR_HANDLER(Incr) \
   {									      \
-    result = __GCONV_ILLEGAL_INPUT;					      \
+    result = __gconv_mark_illegal_input (step_data);			      \
 									      \
     if (irreversible == NULL)						      \
       /* This means we are in call from __gconv_transliterate.  In this	      \
diff --git a/iconv/tst-iconv-sticky-input-error.c b/iconv/tst-iconv-sticky-input-error.c
new file mode 100644
index 0000000000..c93b5b5160
--- /dev/null
+++ b/iconv/tst-iconv-sticky-input-error.c
@@ -0,0 +1,135 @@
+/* Test __GCONV_ENCOUNTERED_ILLEGAL_INPUT, as used by iconv -c (bug 32046).
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+
+#include <array_length.h>
+#include <errno.h>
+#include <gconv_int.h>
+#include <iconv.h>
+#include <stdbool.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/test-driver.h>
+#include <stdio.h>
+
+/* FROM is the input character set, TO the output character set.  If
+   IGNORE is true, the iconv descriptor is set up in the same way as
+   iconv -c would.  INPUT is the input string, EXPECTED_OUTPUT the
+   output.  OUTPUT_LIMIT is a byte count, specifying how many input
+   bytes are passed to the iconv function on each invocation.  */
+static void
+one_direction (const char *from, const char *to, bool ignore,
+               const char *input, const char *expected_output,
+               size_t output_limit)
+{
+  if (test_verbose)
+    {
+      printf ("info: testing from=\"%s\" to=\"%s\" ignore=%d input=\"",
+              from, to, (int) ignore);
+      for (const char *p = input; *p != '\0'; ++p)
+        if (*p >= ' ' && *p <= '~' && *p != '\\' && *p != '"')
+          putchar (*p);
+        else
+          printf ("\\x%02x", *p & 0xff);
+      printf (" \" expected_output=\"%s\" output_limit=%zu\n",
+              expected_output, output_limit);
+    }
+
+  __gconv_t cd;
+  if (ignore)
+    {
+      struct gconv_spec conv_spec;
+      TEST_VERIFY_EXIT (__gconv_create_spec (&conv_spec, from, to)
+                        == &conv_spec);
+      conv_spec.ignore = true;
+      cd = (iconv_t) -1;
+      TEST_COMPARE (__gconv_open (&conv_spec, &cd, 0), __GCONV_OK);
+    }
+  else
+    cd = iconv_open (to, from);
+  TEST_VERIFY_EXIT (cd != (iconv_t) -1);
+
+  char *input_ptr = (char *) input;
+  size_t input_len = strlen (input);
+  char output_buf[20];
+  char *output_ptr = output_buf;
+  size_t output_len;
+  do
+    {
+      output_len = array_end (output_buf) - output_ptr;
+      if (output_len > output_limit)
+        /* Limit the buffer size as requested by the caller.  */
+        output_len = output_limit;
+      TEST_VERIFY_EXIT (output_len > 0);
+      if (input_len == 0)
+        /* Trigger final flush.  */
+        input_ptr = NULL;
+      char *old_input_ptr = input_ptr;
+      size_t ret = iconv (cd, &input_ptr, &input_len,
+                          &output_ptr, &output_len);
+      if (ret == (size_t) -1)
+        {
+          if (errno != EILSEQ)
+            TEST_COMPARE (errno, E2BIG);
+        }
+
+      if (input_ptr == old_input_ptr)
+        /* Avoid endless loop if stuck on an invalid input character.  */
+        break;
+    }
+  while (input_ptr != NULL);
+
+  /* Test the sticky illegal input bit.  */
+  TEST_VERIFY (__gconv_has_illegal_input (cd));
+
+  TEST_COMPARE_BLOB (expected_output, strlen (expected_output),
+                     output_buf, output_ptr - output_buf);
+
+  TEST_COMPARE (iconv_close (cd), 0);
+}
+
+static int
+do_test (void)
+{
+  static const char charsets[][14] =
+    {
+      "ASCII",
+      "ASCII//IGNORE",
+      "UTF-8",
+      "UTF-8//IGNORE",
+    };
+
+  for (size_t from_idx = 0; from_idx < array_length (charsets); ++from_idx)
+    for (size_t to_idx = 0; to_idx < array_length (charsets); ++to_idx)
+      for (int do_ignore = 0; do_ignore < 2; ++do_ignore)
+        for (int limit = 1; limit < 5; ++limit)
+          for (int skip = 0; skip < 3; ++skip)
+            {
+              const char *expected_output;
+              if (do_ignore || strstr (charsets[to_idx], "//IGNORE") != NULL)
+                expected_output = "ABXY" + skip;
+              else
+                expected_output = "AB" + skip;
+              one_direction (charsets[from_idx], charsets[to_idx], do_ignore,
+                             "AB\xffXY" + skip, expected_output, limit);
+            }
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/iconv/tst-iconv_prog-buffer.sh b/iconv/tst-iconv_prog-buffer.sh
index a27107f02b..5ff99a02a3 100644
--- a/iconv/tst-iconv_prog-buffer.sh
+++ b/iconv/tst-iconv_prog-buffer.sh
@@ -150,9 +150,8 @@ expect_exit 1 \
 ! test -s "$tmp/err"
 expect_files abc def
 
-# FIXME: This is not correct, -c should not change the exit status.
 cp "$tmp/out-template" "$tmp/out"
-run_iconv -c -o "$tmp/out" \
+expect_exit 1 run_iconv -c -o "$tmp/out" \
     "$tmp/abc" "$tmp/0xff-wrapped" "$tmp/def" 2>"$tmp/err"
 ! test -s "$tmp/err"
 expect_files abc xy zt def
diff --git a/iconvdata/cp932.c b/iconvdata/cp932.c
index bf7297b114..3def70a70b 100644
--- a/iconvdata/cp932.c
+++ b/iconvdata/cp932.c
@@ -4559,7 +4559,7 @@ static const char from_ucs4_extra[229][2] =
 	if (! ignore_errors_p ())					      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    result = __gconv_mark_illegal_input (step_data);		      \
 	    break;							      \
 	  }								      \
 									      \
@@ -4599,7 +4599,7 @@ static const char from_ucs4_extra[229][2] =
 	    if (! ignore_errors_p ())					      \
 	      {								      \
 		/* This is an illegal character.  */			      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
+		result = __gconv_mark_illegal_input (step_data);	      \
 		break;							      \
 	      }								      \
 									      \
@@ -4634,7 +4634,7 @@ static const char from_ucs4_extra[229][2] =
 	    if (! ignore_errors_p ())					      \
 	      {								      \
 		/* This is an illegal character.  */			      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
+		result = __gconv_mark_illegal_input (step_data);	      \
 		break;							      \
 	      }								      \
 									      \
diff --git a/iconvdata/euc-jp-ms.c b/iconvdata/euc-jp-ms.c
index d03a0e05bb..96c5325e9d 100644
--- a/iconvdata/euc-jp-ms.c
+++ b/iconvdata/euc-jp-ms.c
@@ -4659,7 +4659,7 @@ static const unsigned char from_ucs4_extra[229][2] =
 	/* This is illegal.  */						      \
 	if (! ignore_errors_p ())					      \
 	  {								      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    result = __gconv_mark_illegal_input (step_data);		      \
 	    break;							      \
 	  }								      \
 									      \
@@ -4689,7 +4689,7 @@ static const unsigned char from_ucs4_extra[229][2] =
 	    /* This is an illegal character.  */			      \
 	    if (! ignore_errors_p ())					      \
 	      {								      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
+		result = __gconv_mark_illegal_input (step_data);	      \
 		break;							      \
 	      }								      \
 									      \
@@ -4709,7 +4709,7 @@ static const unsigned char from_ucs4_extra[229][2] =
 		if (! ignore_errors_p ())				      \
 		  {							      \
 		    /* This is an illegal character.  */		      \
-		    result = __GCONV_ILLEGAL_INPUT;			      \
+		    result = __gconv_mark_illegal_input (step_data);	      \
 		    break;						      \
 		  }							      \
 	      }								      \
@@ -4820,7 +4820,7 @@ static const unsigned char from_ucs4_extra[229][2] =
 		if (! ignore_errors_p ())				      \
 		  {							      \
 		    /* This is an illegal character.  */		      \
-		    result = __GCONV_ILLEGAL_INPUT;			      \
+		    result = __gconv_mark_illegal_input (step_data);	      \
 		    break;						      \
 		  }							      \
 									      \
diff --git a/iconvdata/gbbig5.c b/iconvdata/gbbig5.c
index f05deeeb1a..b15a2ef932 100644
--- a/iconvdata/gbbig5.c
+++ b/iconvdata/gbbig5.c
@@ -4831,7 +4831,7 @@ const char __from_big5_to_gb2312 [13973][2] =
 	  {								      \
 	    /* We do not have a mapping for this character.		      \
 	       If ignore errors, map it to 0xa1bc - big5 box character */     \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    result = __gconv_mark_illegal_input (step_data);		      \
 	    if (! ignore_errors_p ())					      \
 	      break;							      \
 									      \
@@ -4922,7 +4922,7 @@ const char __from_big5_to_gb2312 [13973][2] =
 	  {								      \
 	    /* We do not have a mapping for this character.		      \
 	       If ignore errors, map it to 0xa1f5 - gb box character */       \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    result = __gconv_mark_illegal_input (step_data);		      \
 	    if (! ignore_errors_p ())					      \
 	      break;							      \
 									      \
diff --git a/iconvdata/ibm1364.c b/iconvdata/ibm1364.c
index 4c37f30e98..d6c8ce7f68 100644
--- a/iconvdata/ibm1364.c
+++ b/iconvdata/ibm1364.c
@@ -179,7 +179,7 @@ enum
 	    /* This is an illegal character.  */			      \
 	    if (! ignore_errors_p ())					      \
 	      {								      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
+		result = __gconv_mark_illegal_input (step_data);	      \
 		break;							      \
 	      }								      \
 	    ++*irreversible;						      \
@@ -219,7 +219,7 @@ enum
 	    /* This is an illegal character.  */			      \
 	    if (! ignore_errors_p ())					      \
 	      {								      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
+		result = __gconv_mark_illegal_input (step_data);	      \
 		break;							      \
 	      }								      \
 	    ++*irreversible;						      \
@@ -300,7 +300,7 @@ enum
 									      \
 	if (! ignore_errors_p ())					      \
 	  {								      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    result = __gconv_mark_illegal_input (step_data);		      \
 	    break;							      \
 	  }								      \
 	++*irreversible;						      \
@@ -332,7 +332,7 @@ enum
 	    /* This is an illegal character.  */			      \
 	    if (! ignore_errors_p ())					      \
 	      {								      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
+		result = __gconv_mark_illegal_input (step_data);	      \
 		break;							      \
 	      }								      \
 	    ++*irreversible;						      \
diff --git a/iconvdata/iso646.c b/iconvdata/iso646.c
index d96e5f86b9..ba7e23f8ac 100644
--- a/iconvdata/iso646.c
+++ b/iconvdata/iso646.c
@@ -313,7 +313,7 @@ gconv_end (struct __gconv_step *data)
 	  ch = 0xf9;							      \
 	else if (var == JP_OCR_B)					      \
 	  /* Illegal character.  */					      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	else if (var == YU)						      \
 	  ch = 0x17e;							      \
 	else if (var == HU)						      \
@@ -387,7 +387,7 @@ gconv_end (struct __gconv_step *data)
 	  ch = 0xec;							      \
 	else if (var == JP_OCR_B)					      \
 	  /* Illegal character.  */					      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	else if (var == YU)						      \
 	  ch = 0x10d;							      \
 	else if (var == HU)						      \
@@ -403,7 +403,7 @@ gconv_end (struct __gconv_step *data)
 	break;								      \
       case 0x80 ... 0xff:						      \
 	/* Illegal character.  */					      \
-	failure = __GCONV_ILLEGAL_INPUT;				      \
+	failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       }									      \
 									      \
@@ -440,17 +440,17 @@ gconv_end (struct __gconv_step *data)
       case 0x23:							      \
 	if (var == GB || var == ES || var == IT || var == FR || var == FR1    \
 	    || var == NO2)						      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0x24:							      \
 	if (var == CN || var == HU || var == CU || var == SE || var == SE2)   \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0x40:							      \
 	if (var == CA || var == CA2 || var == DE || var == ES || var == ES2   \
 	    || var == IT || var == YU || var == HU || var == FR || var == FR1 \
 	    || var == PT || var == PT2 || var == SE2)			      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0x5b:							      \
 	if (var == CA || var == CA2 || var == DE || var == DK || var == ES    \
@@ -458,7 +458,7 @@ gconv_end (struct __gconv_step *data)
 	    || var == HU || var == FR || var == FR1 || var == NO	      \
 	    || var == NO2 || var == PT || var == PT2 || var == SE	      \
 	    || var == SE2)						      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	else if (var == CU)						      \
 	  ch = 0x7d;							      \
 	break;								      \
@@ -468,7 +468,7 @@ gconv_end (struct __gconv_step *data)
 	    || var == YU || var == KR || var == HU || var == CU || var == FR  \
 	    || var == FR1 || var == NO || var == NO2 || var == PT	      \
 	    || var == PT2 || var == SE || var == SE2)			      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0x5d:							      \
 	if (var == CA || var == CA2 || var == DE || var == DK || var == ES    \
@@ -476,17 +476,17 @@ gconv_end (struct __gconv_step *data)
 	    || var == HU || var == FR || var == FR1 || var == NO	      \
 	    || var == NO2 || var == PT || var == PT2 || var == SE	      \
 	    || var == SE2)						      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0x5e:							      \
 	if (var == CA || var == CA2 || var == ES2 || var == YU || var == CU   \
 	    || var == SE2)						      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0x60:							      \
 	if (var == CA || var == CA2 || var == IT || var == JP_OCR_B	      \
 	    || var == YU || var == HU || var == FR || var == SE2)	      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0x7b:							      \
 	if (var == CA || var == CA2 || var == DE || var == DK || var == ES    \
@@ -494,14 +494,14 @@ gconv_end (struct __gconv_step *data)
 	    || var == CU || var == FR || var == FR1 || var == NO	      \
 	    || var == NO2 || var == PT || var == PT2 || var == SE	      \
 	    || var == SE2)						      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0x7c:							      \
 	if (var == CA || var == CA2 || var == DE || var == DK || var == ES    \
 	    || var == ES2 || var == IT || var == YU || var == HU || var == CU \
 	    || var == FR || var == FR1 || var == NO || var == PT	      \
 	    || var == PT2 || var == SE || var == SE2)			      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	else if (var == NO2)						      \
 	  ch = 0x7e;							      \
 	break;								      \
@@ -510,7 +510,7 @@ gconv_end (struct __gconv_step *data)
 	    || var == ES2 || var == IT || var == YU || var == HU || var == CU \
 	    || var == FR || var == FR1 || var == NO || var == NO2	      \
 	    || var == PT || var == PT2 || var == SE || var == SE2)	      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0x7e:							      \
 	if (var == GB || var == CA || var == CA2 || var == DE || var == ES2   \
@@ -518,21 +518,21 @@ gconv_end (struct __gconv_step *data)
 	    || var == YU || var == HU || var == CU || var == FR || var == FR1 \
 	    || var == NO || var == NO2 || var == PT || var == SE	      \
 	    || var == SE2)						      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0xa1:							      \
 	if (var != ES && var != ES2 && var != CU)			      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5b;							      \
 	break;								      \
       case 0xa3:							      \
 	if (var != GB && var != ES && var != IT && var != FR && var != FR1)   \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x23;							      \
 	break;								      \
       case 0xa4:							      \
 	if (var != HU && var != CU && var != SE && var != SE2)		      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x24;							      \
 	break;								      \
       case 0xa5:							      \
@@ -541,7 +541,7 @@ gconv_end (struct __gconv_step *data)
 	else if (var == JP || var == JP_OCR_B)				      \
 	  ch = 0x5c;							      \
 	else								      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0xa7:							      \
 	if (var == DE || var == ES || var == IT || var == PT)		      \
@@ -551,11 +551,11 @@ gconv_end (struct __gconv_step *data)
 	else if (var == NO2)						      \
 	  ch = 0x23;							      \
 	else								      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0xa8:							      \
 	if (var != ES2 && var != CU && var != FR && var != FR1)		      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7e;							      \
 	break;								      \
       case 0xb0:							      \
@@ -566,7 +566,7 @@ gconv_end (struct __gconv_step *data)
 	else if (var == PT)						      \
 	  ch = 0x7e;							      \
 	else								      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0xb4:							      \
 	if (var == ES2 || var == CU)					      \
@@ -574,11 +574,11 @@ gconv_end (struct __gconv_step *data)
 	else if (var == PT2)						      \
 	  ch = 0x40;							      \
 	else								      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0xb5:							      \
 	if (var != FR)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x60;							      \
 	break;								      \
       case 0xbf:							      \
@@ -587,31 +587,31 @@ gconv_end (struct __gconv_step *data)
 	else if (var == ES2 || var == CU)				      \
 	  ch = 0x5e;							      \
 	else								      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0xc1:							      \
 	if (var != HU)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x40;							      \
 	break;								      \
       case 0xc3:							      \
 	if (var != PT && var != PT2)					      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5b;							      \
 	break;								      \
       case 0xc4:							      \
 	if (var != DE && var != SE && var != SE2)			      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5b;							      \
 	break;								      \
       case 0xc5:							      \
 	if (var != DK && var != NO && var != NO2 && var != SE && var != SE2)  \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5d;							      \
 	break;								      \
       case 0xc6:							      \
 	if (var != DK && var != NO && var != NO2)			      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5b;							      \
 	break;								      \
       case 0xc7:							      \
@@ -620,7 +620,7 @@ gconv_end (struct __gconv_step *data)
 	else if (var == PT || var == PT2)				      \
 	  ch = 0x5c;							      \
 	else								      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0xc9:							      \
 	if (var == CA2)							      \
@@ -630,26 +630,26 @@ gconv_end (struct __gconv_step *data)
 	else if (var == SE2)						      \
 	  ch = 0x40;							      \
 	else								      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0xd1:							      \
 	if (var != ES && var != ES2 && var != CU)			      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5c;							      \
 	break;								      \
       case 0xd5:							      \
 	if (var != PT && var != PT2)					      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5d;							      \
 	break;								      \
       case 0xd6:							      \
 	if (var != DE && var != HU && var != SE && var != SE2)		      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5c;							      \
 	break;								      \
       case 0xd8:							      \
 	if (var != DK && var != NO && var != NO2)			      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5c;							      \
 	break;								      \
       case 0xdc:							      \
@@ -658,11 +658,11 @@ gconv_end (struct __gconv_step *data)
 	else if (var == SE2)						      \
 	  ch = 0x5e;							      \
 	else								      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0xdf:							      \
 	if (var != DE)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7e;							      \
 	break;								      \
       case 0xe0:							      \
@@ -671,36 +671,36 @@ gconv_end (struct __gconv_step *data)
 	else if (var == IT)						      \
 	  ch = 0x7b;							      \
 	else								      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0xe1:							      \
 	if (var != HU)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x60;							      \
 	break;								      \
       case 0xe2:							      \
 	if (var != CA && var != CA2)					      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5b;							      \
 	break;								      \
       case 0xe3:							      \
 	if (var != PT && var != PT2)					      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7b;							      \
 	break;								      \
       case 0xe4:							      \
 	if (var != DE && var != SE && var != SE2)			      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7b;							      \
 	break;								      \
       case 0xe5:							      \
 	if (var != DK && var != NO && var != NO2 && var != SE && var != SE2)  \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7d;							      \
 	break;								      \
       case 0xe6:							      \
 	if (var != DK && var != NO && var != NO2)			      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7b;							      \
 	break;								      \
       case 0xe7:							      \
@@ -711,11 +711,11 @@ gconv_end (struct __gconv_step *data)
 	else if (var == PT || var == PT2)				      \
 	  ch = 0x7c;							      \
 	else								      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0xe8:							      \
 	if (var != CA && var != CA2 && var != IT && var != FR && var != FR1)  \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7d;							      \
 	break;								      \
       case 0xe9:							      \
@@ -726,51 +726,51 @@ gconv_end (struct __gconv_step *data)
 	else if (var == SE2)						      \
 	  ch = 0x60;							      \
 	else								      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0xea:							      \
 	if (var != CA && var != CA2)					      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5d;							      \
 	break;								      \
       case 0xec:							      \
 	if (var != IT)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7e;							      \
 	break;								      \
       case 0xee:							      \
 	if (var != CA)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5e;							      \
 	break;								      \
       case 0xf1:							      \
 	if (var != ES && var != ES2 && var != CU)			      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7c;							      \
 	break;								      \
       case 0xf2:							      \
 	if (var != IT)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7c;							      \
 	break;								      \
       case 0xf4:							      \
 	if (var != CA && var != CA2)					      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x60;							      \
 	break;								      \
       case 0xf5:							      \
 	if (var != PT && var != PT2)					      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7d;							      \
 	break;								      \
       case 0xf6:							      \
 	if (var != DE && var != HU && var != SE && var != SE2)		      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7c;							      \
 	break;								      \
       case 0xf8:							      \
 	if (var != DK && var != NO && var != NO2)			      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7c;							      \
 	break;								      \
       case 0xf9:							      \
@@ -779,11 +779,11 @@ gconv_end (struct __gconv_step *data)
 	else if (var == IT)						      \
 	  ch = 0x60;							      \
 	else								      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0xfb:							      \
 	if (var != CA && var != CA2)					      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7e;							      \
 	break;								      \
       case 0xfc:							      \
@@ -792,93 +792,93 @@ gconv_end (struct __gconv_step *data)
 	else if (var == SE2)						      \
 	  ch = 0x7e;							      \
 	else								      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	break;								      \
       case 0x160:							      \
 	if (var != YU)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5b;							      \
 	break;								      \
       case 0x106:							      \
 	if (var != YU)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5d;							      \
 	break;								      \
       case 0x107:							      \
 	if (var != YU)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7d;							      \
 	break;								      \
       case 0x10c:							      \
 	if (var != YU)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5e;							      \
 	break;								      \
       case 0x10d:							      \
 	if (var != YU)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7e;							      \
 	break;								      \
       case 0x110:							      \
 	if (var != YU)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5c;							      \
 	break;								      \
       case 0x111:							      \
 	if (var != YU)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7c;							      \
 	break;								      \
       case 0x161:							      \
 	if (var != YU)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7b;							      \
 	break;								      \
       case 0x17d:							      \
 	if (var != YU)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x40;							      \
 	break;								      \
       case 0x17e:							      \
 	if (var != YU)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x60;							      \
 	break;								      \
       case 0x2dd:							      \
 	if (var != HU)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7e;							      \
 	break;								      \
       case 0x2022:							      \
 	if (var != ES2)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x40;							      \
 	break;								      \
       case 0x203e:							      \
 	if (var != GB && var != CN && var != JP && var != NO && var != SE)    \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x7e;							      \
 	break;								      \
       case 0x20a9:							      \
 	if (var != KR)							      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5c;							      \
 	break;								      \
       case 0x2329:							      \
 	if (var != JP_OCR_B)						      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5b;							      \
 	break;								      \
       case 0x232a:							      \
 	if (var != JP_OCR_B)						      \
-	  failure = __GCONV_ILLEGAL_INPUT;				      \
+	  failure = __gconv_mark_illegal_input (step_data);		      \
 	ch = 0x5d;							      \
 	break;								      \
       default:								      \
 	if (__glibc_unlikely (ch > 0x7f))				      \
 	  {								      \
 	    UNICODE_TAG_HANDLER (ch, 4);				      \
-	    failure = __GCONV_ILLEGAL_INPUT;				      \
+	    failure = __gconv_mark_illegal_input (step_data);		      \
 	  }								      \
 	break;								      \
       }									      \
diff --git a/iconvdata/unicode.c b/iconvdata/unicode.c
index d69c9887a1..79bb9886e5 100644
--- a/iconvdata/unicode.c
+++ b/iconvdata/unicode.c
@@ -163,7 +163,7 @@ gconv_end (struct __gconv_step *data)
 	   surrogates pass through, attackers could make a security	      \
 	   hole exploit by synthesizing any desired plane 1-16		      \
 	   character.  */						      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
+	result = __gconv_mark_illegal_input (step_data);		      \
 	if (! ignore_errors_p ())					      \
 	  break;							      \
 	inptr += 4;							      \
diff --git a/iconvdata/utf-16.c b/iconvdata/utf-16.c
index a869353f20..9d9fd2a2a3 100644
--- a/iconvdata/utf-16.c
+++ b/iconvdata/utf-16.c
@@ -206,7 +206,7 @@ gconv_end (struct __gconv_step *data)
 	   We must catch this.  If we let surrogates pass through,	      \
 	   attackers could make a security hole exploit by		      \
 	   synthesizing any desired plane 1-16 character.  */		      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
+	result = __gconv_mark_illegal_input (step_data);		      \
 	if (! ignore_errors_p ())					      \
 	  break;							      \
 	inptr += 4;							      \
diff --git a/iconvdata/utf-32.c b/iconvdata/utf-32.c
index 5693b48975..139eefb6d8 100644
--- a/iconvdata/utf-32.c
+++ b/iconvdata/utf-32.c
@@ -207,7 +207,7 @@ gconv_end (struct __gconv_step *data)
 	   We must catch this.  If we let surrogates pass through,	      \
 	   attackers could make a security hole exploit by		      \
 	   generating "irregular UTF-32" sequences.  */			      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
+	result = __gconv_mark_illegal_input (step_data);		      \
 	if (! ignore_errors_p ())					      \
 	  break;							      \
 	inptr += 4;							      \
