Print this page
12364 mdb trips assertion related to autowrap

*** 22,32 **** * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* ! * Copyright (c) 2019, Joyent, Inc. All rights reserved. * Copyright (c) 2016 by Delphix. All rights reserved. */ /* * MDB uses its own enhanced standard i/o mechanism for all input and output. --- 22,32 ---- * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* ! * 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,1784 **** --- 1775,1805 ---- 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,1831 **** 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 * 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; ! } ! m = MIN(nleft, n); /* copy at most n bytes in this pass */ bcopy(q, iob->iob_bufp, m); nleft -= m; q += m; --- 1829,1843 ---- nleft -= (size_t)(p - q) + 1; /* Update byte count */ q = p + 1; /* Advance past delimiter */ } /* ! * 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) { ! 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,1899 **** 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; ! } ! m = MIN(nfill, n); /* fill at most n bytes in this pass */ for (i = 0; i < m; i++) *iob->iob_bufp++ = (char)c; --- 1894,1904 ---- size_t i, m, n; ASSERT(iob->iob_flags & MDB_IOB_WRONLY); while (nfill != 0) { ! 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,2175 **** --- 2171,2200 ---- 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