Have wuffs_aux's CopyIn compact the dst buffer
diff --git a/internal/cgen/auxiliary/base.cc b/internal/cgen/auxiliary/base.cc
index 3246567..5e09762 100644
--- a/internal/cgen/auxiliary/base.cc
+++ b/internal/cgen/auxiliary/base.cc
@@ -40,7 +40,12 @@
 FileInput::CopyIn(IOBuffer* dst) {
   if (!m_f) {
     return "wuffs_aux::sync_io::FileInput: nullptr file";
-  } else if (dst && !dst->meta.closed) {
+  } else if (!dst) {
+    return "wuffs_aux::sync_io::FileInput: nullptr IOBuffer";
+  } else if (dst->meta.closed) {
+    return "wuffs_aux::sync_io::FileInput: end of file";
+  } else {
+    dst->compact();
     size_t n = fread(dst->writer_pointer(), 1, dst->writer_length(), m_f);
     dst->meta.wi += n;
     dst->meta.closed = feof(m_f);
@@ -69,7 +74,16 @@
 
 std::string  //
 MemoryInput::CopyIn(IOBuffer* dst) {
-  if (dst && !dst->meta.closed && (dst != &m_io)) {
+  if (!dst) {
+    return "wuffs_aux::sync_io::MemoryInput: nullptr IOBuffer";
+  } else if (dst->meta.closed) {
+    return "wuffs_aux::sync_io::MemoryInput: end of file";
+  } else if (wuffs_base__slice_u8__overlaps(dst->data, m_io.data)) {
+    // Treat m_io's data as immutable, so don't compact dst or otherwise write
+    // to it.
+    return "wuffs_aux::sync_io::MemoryInput: overlapping buffers";
+  } else {
+    dst->compact();
     size_t nd = dst->writer_length();
     size_t ns = m_io.reader_length();
     size_t n = (nd < ns) ? nd : ns;
diff --git a/internal/cgen/base/fundamental-public.h b/internal/cgen/base/fundamental-public.h
index cfcc753..20939d8 100644
--- a/internal/cgen/base/fundamental-public.h
+++ b/internal/cgen/base/fundamental-public.h
@@ -1065,6 +1065,12 @@
   return ret;
 }
 
+static inline bool  //
+wuffs_base__slice_u8__overlaps(wuffs_base__slice_u8 s, wuffs_base__slice_u8 t) {
+  return ((s.ptr <= t.ptr) && (t.ptr < (s.ptr + s.len))) ||
+         ((t.ptr <= s.ptr) && (s.ptr < (t.ptr + t.len)));
+}
+
 // wuffs_base__slice_u8__subslice_i returns s[i:].
 //
 // It returns an empty slice if i is out of bounds.
diff --git a/internal/cgen/data/data.go b/internal/cgen/data/data.go
index a157c84..535b79a 100644
--- a/internal/cgen/data/data.go
+++ b/internal/cgen/data/data.go
@@ -111,8 +111,8 @@
 	"// ---------------- Slices and Tables\n\n// WUFFS_BASE__SLICE is a 1-dimensional buffer.\n//\n// len measures a number of elements, not necessarily a size in bytes.\n//\n// A value with all fields NULL or zero is a valid, empty slice.\n#define WUFFS_BASE__SLICE(T) \\\n  struct {                   \\\n    T* ptr;                  \\\n    size_t len;              \\\n  }\n\n// WUFFS_BASE__TABLE is a 2-dimensional buffer.\n//\n// width height, and stride measure a number of elements, not necessarily a\n// size in bytes.\n//\n// A value with all fields NULL or zero is a valid, empty table.\n#define WUFFS_BASE__TABLE(T) \\\n  struct {                   \\\n    T* ptr;                  \\\n    size_t width;            \\\n    size_t height;           \\\n    size_t stride;           \\\n  }\n\ntypedef WUFFS_BASE__SLICE(uint8_t) wuffs_base__slice_u8;\ntypedef WUFFS_BASE__SLICE(uint16_t) wuffs_base__slice_u16;\ntypedef WUFFS_BASE__SLICE(uint32_t) wuffs_base__slice_u32;\ntypedef WUFFS_BASE__SLICE(uint64_t) wuffs_base__slice_u64;\n\ntypedef WUFFS_BASE__TABLE(u" +
 	"int8_t) wuffs_base__table_u8;\ntypedef WUFFS_BASE__TABLE(uint16_t) wuffs_base__table_u16;\ntypedef WUFFS_BASE__TABLE(uint32_t) wuffs_base__table_u32;\ntypedef WUFFS_BASE__TABLE(uint64_t) wuffs_base__table_u64;\n\nstatic inline wuffs_base__slice_u8  //\nwuffs_base__make_slice_u8(uint8_t* ptr, size_t len) {\n  wuffs_base__slice_u8 ret;\n  ret.ptr = ptr;\n  ret.len = len;\n  return ret;\n}\n\nstatic inline wuffs_base__slice_u16  //\nwuffs_base__make_slice_u16(uint16_t* ptr, size_t len) {\n  wuffs_base__slice_u16 ret;\n  ret.ptr = ptr;\n  ret.len = len;\n  return ret;\n}\n\nstatic inline wuffs_base__slice_u32  //\nwuffs_base__make_slice_u32(uint32_t* ptr, size_t len) {\n  wuffs_base__slice_u32 ret;\n  ret.ptr = ptr;\n  ret.len = len;\n  return ret;\n}\n\nstatic inline wuffs_base__slice_u64  //\nwuffs_base__make_slice_u64(uint64_t* ptr, size_t len) {\n  wuffs_base__slice_u64 ret;\n  ret.ptr = ptr;\n  ret.len = len;\n  return ret;\n}\n\nstatic inline wuffs_base__slice_u8  //\nwuffs_base__empty_slice_u8() {\n  wuffs_base__slice_u8 ret;\n  ret.ptr = NULL;\n" +
 	"  ret.len = 0;\n  return ret;\n}\n\nstatic inline wuffs_base__slice_u16  //\nwuffs_base__empty_slice_u16() {\n  wuffs_base__slice_u16 ret;\n  ret.ptr = NULL;\n  ret.len = 0;\n  return ret;\n}\n\nstatic inline wuffs_base__slice_u32  //\nwuffs_base__empty_slice_u32() {\n  wuffs_base__slice_u32 ret;\n  ret.ptr = NULL;\n  ret.len = 0;\n  return ret;\n}\n\nstatic inline wuffs_base__slice_u64  //\nwuffs_base__empty_slice_u64() {\n  wuffs_base__slice_u64 ret;\n  ret.ptr = NULL;\n  ret.len = 0;\n  return ret;\n}\n\nstatic inline wuffs_base__table_u8  //\nwuffs_base__empty_table_u8() {\n  wuffs_base__table_u8 ret;\n  ret.ptr = NULL;\n  ret.width = 0;\n  ret.height = 0;\n  ret.stride = 0;\n  return ret;\n}\n\nstatic inline wuffs_base__table_u16  //\nwuffs_base__empty_table_u16() {\n  wuffs_base__table_u16 ret;\n  ret.ptr = NULL;\n  ret.width = 0;\n  ret.height = 0;\n  ret.stride = 0;\n  return ret;\n}\n\nstatic inline wuffs_base__table_u32  //\nwuffs_base__empty_table_u32() {\n  wuffs_base__table_u32 ret;\n  ret.ptr = NULL;\n  ret.width = 0;\n  ret.height = 0;\n  ret.stri" +
-	"de = 0;\n  return ret;\n}\n\nstatic inline wuffs_base__table_u64  //\nwuffs_base__empty_table_u64() {\n  wuffs_base__table_u64 ret;\n  ret.ptr = NULL;\n  ret.width = 0;\n  ret.height = 0;\n  ret.stride = 0;\n  return ret;\n}\n\n// wuffs_base__slice_u8__subslice_i returns s[i:].\n//\n// It returns an empty slice if i is out of bounds.\nstatic inline wuffs_base__slice_u8  //\nwuffs_base__slice_u8__subslice_i(wuffs_base__slice_u8 s, uint64_t i) {\n  if ((i <= SIZE_MAX) && (i <= s.len)) {\n    return wuffs_base__make_slice_u8(s.ptr + i, ((size_t)(s.len - i)));\n  }\n  return wuffs_base__make_slice_u8(NULL, 0);\n}\n\n// wuffs_base__slice_u8__subslice_j returns s[:j].\n//\n// It returns an empty slice if j is out of bounds.\nstatic inline wuffs_base__slice_u8  //\nwuffs_base__slice_u8__subslice_j(wuffs_base__slice_u8 s, uint64_t j) {\n  if ((j <= SIZE_MAX) && (j <= s.len)) {\n    return wuffs_base__make_slice_u8(s.ptr, ((size_t)j));\n  }\n  return wuffs_base__make_slice_u8(NULL, 0);\n}\n\n// wuffs_base__slice_u8__subslice_ij returns s[i:j].\n//\n// It " +
-	"returns an empty slice if i or j is out of bounds.\nstatic inline wuffs_base__slice_u8  //\nwuffs_base__slice_u8__subslice_ij(wuffs_base__slice_u8 s,\n                                  uint64_t i,\n                                  uint64_t j) {\n  if ((i <= j) && (j <= SIZE_MAX) && (j <= s.len)) {\n    return wuffs_base__make_slice_u8(s.ptr + i, ((size_t)(j - i)));\n  }\n  return wuffs_base__make_slice_u8(NULL, 0);\n}\n\n" +
+	"de = 0;\n  return ret;\n}\n\nstatic inline wuffs_base__table_u64  //\nwuffs_base__empty_table_u64() {\n  wuffs_base__table_u64 ret;\n  ret.ptr = NULL;\n  ret.width = 0;\n  ret.height = 0;\n  ret.stride = 0;\n  return ret;\n}\n\nstatic inline bool  //\nwuffs_base__slice_u8__overlaps(wuffs_base__slice_u8 s, wuffs_base__slice_u8 t) {\n  return ((s.ptr <= t.ptr) && (t.ptr < (s.ptr + s.len))) ||\n         ((t.ptr <= s.ptr) && (s.ptr < (t.ptr + t.len)));\n}\n\n// wuffs_base__slice_u8__subslice_i returns s[i:].\n//\n// It returns an empty slice if i is out of bounds.\nstatic inline wuffs_base__slice_u8  //\nwuffs_base__slice_u8__subslice_i(wuffs_base__slice_u8 s, uint64_t i) {\n  if ((i <= SIZE_MAX) && (i <= s.len)) {\n    return wuffs_base__make_slice_u8(s.ptr + i, ((size_t)(s.len - i)));\n  }\n  return wuffs_base__make_slice_u8(NULL, 0);\n}\n\n// wuffs_base__slice_u8__subslice_j returns s[:j].\n//\n// It returns an empty slice if j is out of bounds.\nstatic inline wuffs_base__slice_u8  //\nwuffs_base__slice_u8__subslice_j(wuffs_base__slice_u8 s, ui" +
+	"nt64_t j) {\n  if ((j <= SIZE_MAX) && (j <= s.len)) {\n    return wuffs_base__make_slice_u8(s.ptr, ((size_t)j));\n  }\n  return wuffs_base__make_slice_u8(NULL, 0);\n}\n\n// wuffs_base__slice_u8__subslice_ij returns s[i:j].\n//\n// It returns an empty slice if i or j is out of bounds.\nstatic inline wuffs_base__slice_u8  //\nwuffs_base__slice_u8__subslice_ij(wuffs_base__slice_u8 s,\n                                  uint64_t i,\n                                  uint64_t j) {\n  if ((i <= j) && (j <= SIZE_MAX) && (j <= s.len)) {\n    return wuffs_base__make_slice_u8(s.ptr + i, ((size_t)(j - i)));\n  }\n  return wuffs_base__make_slice_u8(NULL, 0);\n}\n\n" +
 	"" +
 	"// ---------------- Magic Numbers\n\n// wuffs_base__magic_number_guess_fourcc guesses the file format of some data,\n// given its opening bytes. It returns a positive FourCC value on success.\n//\n// It returns zero if nothing matches its hard-coded list of 'magic numbers'.\n//\n// It returns a negative value if a longer prefix is required for a conclusive\n// result. For example, seeing a single 'B' byte is not enough to discriminate\n// the BMP and BPG image file formats.\n//\n// It does not do a full validity check. Like any guess made from a short\n// prefix of the data, it may return false positives. Data that starts with 99\n// bytes of valid JPEG followed by corruption or truncation is an invalid JPEG\n// image overall, but this function will still return WUFFS_BASE__FOURCC__JPEG.\n//\n// Another source of false positives is that some 'magic numbers' are valid\n// ASCII data. A file starting with \"GIF87a and GIF89a are the two versions of\n// GIF\" will match GIF's 'magic number' even if it's plain text, not an image.\n//" +
 	"\n// For modular builds that divide the base module into sub-modules, using this\n// function requires the WUFFS_CONFIG__MODULE__BASE__MAGIC sub-module, not just\n// WUFFS_CONFIG__MODULE__BASE__CORE.\nWUFFS_BASE__MAYBE_STATIC int32_t  //\nwuffs_base__magic_number_guess_fourcc(wuffs_base__slice_u8 prefix);\n" +
@@ -690,9 +690,10 @@
 	"" +
 	"// --------\n\nIOBuffer*  //\nInput::BringsItsOwnIOBuffer() {\n  return nullptr;\n}\n\n" +
 	"" +
-	"// --------\n\nFileInput::FileInput(FILE* f) : m_f(f) {}\n\nstd::string  //\nFileInput::CopyIn(IOBuffer* dst) {\n  if (!m_f) {\n    return \"wuffs_aux::sync_io::FileInput: nullptr file\";\n  } else if (dst && !dst->meta.closed) {\n    size_t n = fread(dst->writer_pointer(), 1, dst->writer_length(), m_f);\n    dst->meta.wi += n;\n    dst->meta.closed = feof(m_f);\n    if (ferror(m_f)) {\n      return \"wuffs_aux::sync_io::FileInput: error reading file\";\n    }\n  }\n  return \"\";\n}\n\n" +
+	"// --------\n\nFileInput::FileInput(FILE* f) : m_f(f) {}\n\nstd::string  //\nFileInput::CopyIn(IOBuffer* dst) {\n  if (!m_f) {\n    return \"wuffs_aux::sync_io::FileInput: nullptr file\";\n  } else if (!dst) {\n    return \"wuffs_aux::sync_io::FileInput: nullptr IOBuffer\";\n  } else if (dst->meta.closed) {\n    return \"wuffs_aux::sync_io::FileInput: end of file\";\n  } else {\n    dst->compact();\n    size_t n = fread(dst->writer_pointer(), 1, dst->writer_length(), m_f);\n    dst->meta.wi += n;\n    dst->meta.closed = feof(m_f);\n    if (ferror(m_f)) {\n      return \"wuffs_aux::sync_io::FileInput: error reading file\";\n    }\n  }\n  return \"\";\n}\n\n" +
 	"" +
-	"// --------\n\nMemoryInput::MemoryInput(const char* ptr, size_t len)\n    : m_io(wuffs_base__ptr_u8__reader(\n          static_cast<uint8_t*>(static_cast<void*>(const_cast<char*>(ptr))),\n          len,\n          true)) {}\n\nMemoryInput::MemoryInput(const uint8_t* ptr, size_t len)\n    : m_io(wuffs_base__ptr_u8__reader(const_cast<uint8_t*>(ptr), len, true)) {}\n\nIOBuffer*  //\nMemoryInput::BringsItsOwnIOBuffer() {\n  return &m_io;\n}\n\nstd::string  //\nMemoryInput::CopyIn(IOBuffer* dst) {\n  if (dst && !dst->meta.closed && (dst != &m_io)) {\n    size_t nd = dst->writer_length();\n    size_t ns = m_io.reader_length();\n    size_t n = (nd < ns) ? nd : ns;\n    memcpy(dst->writer_pointer(), m_io.reader_pointer(), n);\n    m_io.meta.ri += n;\n    dst->meta.wi += n;\n    dst->meta.closed = m_io.reader_length() == 0;\n  }\n  return \"\";\n}\n\n" +
+	"// --------\n\nMemoryInput::MemoryInput(const char* ptr, size_t len)\n    : m_io(wuffs_base__ptr_u8__reader(\n          static_cast<uint8_t*>(static_cast<void*>(const_cast<char*>(ptr))),\n          len,\n          true)) {}\n\nMemoryInput::MemoryInput(const uint8_t* ptr, size_t len)\n    : m_io(wuffs_base__ptr_u8__reader(const_cast<uint8_t*>(ptr), len, true)) {}\n\nIOBuffer*  //\nMemoryInput::BringsItsOwnIOBuffer() {\n  return &m_io;\n}\n\nstd::string  //\nMemoryInput::CopyIn(IOBuffer* dst) {\n  if (!dst) {\n    return \"wuffs_aux::sync_io::MemoryInput: nullptr IOBuffer\";\n  } else if (dst->meta.closed) {\n    return \"wuffs_aux::sync_io::MemoryInput: end of file\";\n  } else if (wuffs_base__slice_u8__overlaps(dst->data, m_io.data)) {\n    // Treat m_io's data as immutable, so don't compact dst or otherwise write\n    // to it.\n    return \"wuffs_aux::sync_io::MemoryInput: overlapping buffers\";\n  } else {\n    dst->compact();\n    size_t nd = dst->writer_length();\n    size_t ns = m_io.reader_length();\n    size_t n = (nd < ns) ? nd : ns;\n " +
+	"   memcpy(dst->writer_pointer(), m_io.reader_pointer(), n);\n    m_io.meta.ri += n;\n    dst->meta.wi += n;\n    dst->meta.closed = m_io.reader_length() == 0;\n  }\n  return \"\";\n}\n\n" +
 	"" +
 	"// --------\n\n}  // namespace sync_io\n\n}  // namespace wuffs_aux\n\n#endif  // !defined(WUFFS_CONFIG__MODULES) ||\n        // defined(WUFFS_CONFIG__MODULE__AUX__BASE)\n" +
 	""
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 82d30ed..ac2284e 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -1271,6 +1271,12 @@
   return ret;
 }
 
+static inline bool  //
+wuffs_base__slice_u8__overlaps(wuffs_base__slice_u8 s, wuffs_base__slice_u8 t) {
+  return ((s.ptr <= t.ptr) && (t.ptr < (s.ptr + s.len))) ||
+         ((t.ptr <= s.ptr) && (s.ptr < (t.ptr + t.len)));
+}
+
 // wuffs_base__slice_u8__subslice_i returns s[i:].
 //
 // It returns an empty slice if i is out of bounds.
@@ -36065,7 +36071,12 @@
 FileInput::CopyIn(IOBuffer* dst) {
   if (!m_f) {
     return "wuffs_aux::sync_io::FileInput: nullptr file";
-  } else if (dst && !dst->meta.closed) {
+  } else if (!dst) {
+    return "wuffs_aux::sync_io::FileInput: nullptr IOBuffer";
+  } else if (dst->meta.closed) {
+    return "wuffs_aux::sync_io::FileInput: end of file";
+  } else {
+    dst->compact();
     size_t n = fread(dst->writer_pointer(), 1, dst->writer_length(), m_f);
     dst->meta.wi += n;
     dst->meta.closed = feof(m_f);
@@ -36094,7 +36105,16 @@
 
 std::string  //
 MemoryInput::CopyIn(IOBuffer* dst) {
-  if (dst && !dst->meta.closed && (dst != &m_io)) {
+  if (!dst) {
+    return "wuffs_aux::sync_io::MemoryInput: nullptr IOBuffer";
+  } else if (dst->meta.closed) {
+    return "wuffs_aux::sync_io::MemoryInput: end of file";
+  } else if (wuffs_base__slice_u8__overlaps(dst->data, m_io.data)) {
+    // Treat m_io's data as immutable, so don't compact dst or otherwise write
+    // to it.
+    return "wuffs_aux::sync_io::MemoryInput: overlapping buffers";
+  } else {
+    dst->compact();
     size_t nd = dst->writer_length();
     size_t ns = m_io.reader_length();
     size_t n = (nd < ns) ? nd : ns;