Print this page
12364 mdb trips assertion related to autowrap
@@ -22,11 +22,11 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
- * Copyright (c) 2019, Joyent, Inc. All rights reserved.
+ * Copyright 2020 Joyent, Inc.
* Copyright (c) 2016 by Delphix. All rights reserved.
*/
/*
* MDB uses its own enhanced standard i/o mechanism for all input and output.
@@ -1775,10 +1775,31 @@
va_end(alist);
return (nbytes);
}
+/*
+ * Return how many bytes we can copy into our buffer, limited by either cols or
+ * bufsiz depending on whether AUTOWRAP is on. Note that typically,
+ * mdb_iob_set_autowrap() will have already checked for an existing
+ * "->iob_nbytes > ->iob_cols" situation, but we double check here anyway.
+ */
+static size_t
+iob_bufleft(mdb_iob_t *iob)
+{
+ if (IOB_AUTOWRAP(iob)) {
+ if (iob->iob_cols < iob->iob_nbytes) {
+ mdb_iob_nl(iob);
+ ASSERT(iob->iob_cols >= iob->iob_nbytes);
+ }
+ return (iob->iob_cols - iob->iob_nbytes);
+ }
+
+ ASSERT(iob->iob_bufsiz >= iob->iob_nbytes);
+ return (iob->iob_bufsiz - iob->iob_nbytes);
+}
+
void
mdb_iob_nputs(mdb_iob_t *iob, const char *s, size_t nbytes)
{
size_t m, n, nleft = nbytes;
const char *p, *q = s;
@@ -1808,24 +1829,15 @@
nleft -= (size_t)(p - q) + 1; /* Update byte count */
q = p + 1; /* Advance past delimiter */
}
/*
- * For a given string component, we determine how many bytes (n) we can
- * copy into our buffer (limited by either cols or bufsiz depending
- * on whether AUTOWRAP is on), copy a chunk into the buffer, and
+ * For a given string component, we copy a chunk into the buffer, and
* flush the buffer if we reach the end of a line.
*/
while (nleft != 0) {
- if (IOB_AUTOWRAP(iob)) {
- ASSERT(iob->iob_cols >= iob->iob_nbytes);
- n = iob->iob_cols - iob->iob_nbytes;
- } else {
- ASSERT(iob->iob_bufsiz >= iob->iob_nbytes);
- n = iob->iob_bufsiz - iob->iob_nbytes;
- }
-
+ n = iob_bufleft(iob);
m = MIN(nleft, n); /* copy at most n bytes in this pass */
bcopy(q, iob->iob_bufp, m);
nleft -= m;
q += m;
@@ -1882,18 +1894,11 @@
size_t i, m, n;
ASSERT(iob->iob_flags & MDB_IOB_WRONLY);
while (nfill != 0) {
- if (IOB_AUTOWRAP(iob)) {
- ASSERT(iob->iob_cols >= iob->iob_nbytes);
- n = iob->iob_cols - iob->iob_nbytes;
- } else {
- ASSERT(iob->iob_bufsiz >= iob->iob_nbytes);
- n = iob->iob_bufsiz - iob->iob_nbytes;
- }
-
+ n = iob_bufleft(iob);
m = MIN(nfill, n); /* fill at most n bytes in this pass */
for (i = 0; i < m; i++)
*iob->iob_bufp++ = (char)c;
@@ -2166,10 +2171,30 @@
mdb_iob_stack_size(mdb_iob_stack_t *stk)
{
return (stk->stk_size);
}
+/*
+ * This only enables autowrap for iobs that are already autowrap themselves such
+ * as mdb.m_out typically.
+ *
+ * Note that we might be the middle of the iob buffer at this point, and
+ * specifically, iob->iob_nbytes could be more than iob->iob_cols. As that's
+ * not a valid situation, we may need to do an autowrap *now*.
+ *
+ * In theory, we would need to do this across all MDB_IOB_AUTOWRAP iob's;
+ * instead, we have a failsafe in iob_bufleft().
+ */
+void
+mdb_iob_set_autowrap(mdb_iob_t *iob)
+{
+ mdb.m_flags |= MDB_FL_AUTOWRAP;
+ if (IOB_WRAPNOW(iob, 0))
+ mdb_iob_nl(iob);
+ ASSERT(iob->iob_cols >= iob->iob_nbytes);
+}
+
/*
* Stub functions for i/o backend implementors: these stubs either act as
* pass-through no-ops or return ENOTSUP as appropriate.
*/
ssize_t