diff --git a/libio/genops.c b/libio/genops.c
index c673c0acec..fb06245467 100644
--- a/libio/genops.c
+++ b/libio/genops.c
@@ -789,6 +789,12 @@ _IO_unbuffer_all (void)
legacy = 1;
#endif
+ /* Free up the backup area if it was ever allocated. */
+ if (_IO_have_backup (fp))
+ _IO_free_backup_area (fp);
+ if (fp->_mode > 0 && _IO_have_wbackup (fp))
+ _IO_free_wbackup_area (fp);
+
if (! (fp->_flags & _IO_UNBUFFERED)
/* Iff stream is un-orientated, it wasn't used. */
&& (legacy || fp->_mode != 0))
diff --git a/libio/libioP.h b/libio/libioP.h
index 745278e076..e75ee770bc 100644
--- a/libio/libioP.h
+++ b/libio/libioP.h
@@ -577,8 +577,8 @@ extern void _IO_old_init (FILE *fp, int flags) __THROW;
((__fp)->_wide_data->_IO_write_base \
= (__fp)->_wide_data->_IO_write_ptr = __p, \
(__fp)->_wide_data->_IO_write_end = (__ep))
-#define _IO_have_backup(fp) ((fp)->_IO_save_base != NULL)
-#define _IO_have_wbackup(fp) ((fp)->_wide_data->_IO_save_base != NULL)
+#define _IO_have_backup(fp) ((fp)->_IO_backup_base != NULL)
+#define _IO_have_wbackup(fp) ((fp)->_wide_data->_IO_backup_base != NULL)
#define _IO_in_backup(fp) ((fp)->_flags & _IO_IN_BACKUP)
#define _IO_have_markers(fp) ((fp)->_markers != NULL)
#define _IO_blen(fp) ((fp)->_IO_buf_end - (fp)->_IO_buf_base)
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 2bcbaf754a..381040570b 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -256,6 +256,7 @@ tests := \
tst-swscanf \
tst-tmpnam \
tst-ungetc \
+ tst-ungetc-leak \
tst-unlockedio \
tst-vfprintf-mbs-prec \
tst-vfprintf-user-type \
@@ -300,6 +301,7 @@ tests-special += \
$(objpfx)tst-printfsz-islongdouble.out \
$(objpfx)tst-setvbuf1-cmp.out \
$(objpfx)tst-unbputc.out \
+ $(objpfx)tst-ungetc-leak-mem.out \
$(objpfx)tst-vfprintf-width-prec-mem.out \
# tests-special
@@ -314,6 +316,8 @@ generated += \
tst-printf-fp-leak-mem.out \
tst-printf-fp-leak.mtrace \
tst-scanf-bz27650.mtrace \
+ tst-ungetc-leak-mem.out \
+ tst-ungetc-leak.mtrace \
tst-vfprintf-width-prec-mem.out \
tst-vfprintf-width-prec.mtrace \
# generated
@@ -403,6 +407,9 @@ tst-printf-fp-leak-ENV = \
tst-scanf-bz27650-ENV = \
MALLOC_TRACE=$(objpfx)tst-scanf-bz27650.mtrace \
LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
+tst-ungetc-leak-ENV = \
+ MALLOC_TRACE=$(objpfx)tst-ungetc-leak.mtrace \
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
$(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \
diff --git a/stdio-common/tst-ungetc-leak.c b/stdio-common/tst-ungetc-leak.c
new file mode 100644
index 0000000000..6c5152b43f
--- /dev/null
+++ b/stdio-common/tst-ungetc-leak.c
@@ -0,0 +1,32 @@
+/* Test for memory leak with ungetc when stream is unused.
+ Copyright The GNU Toolchain Authors.
+ 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
+ . */
+
+#include
+#include
+#include
+#include
+
+static int
+do_test (void)
+{
+ mtrace ();
+ TEST_COMPARE (ungetc('y', stdin), 'y');
+ return 0;
+}
+
+#include