* Construct a query prompt string, based around an object name, which is * guaranteed to fit within [QBUFSZ]. Takes an optional prefix, three * choices for filling in the middle (two object formatting functions and a * last resort literal which should be very short), and an optional suffix. */
| 5621 | * last resort literal which should be very short), and an optional suffix. |
| 5622 | */ |
| 5623 | char * |
| 5624 | safe_qbuf( |
| 5625 | char *qbuf, /* output buffer */ |
| 5626 | const char *qprefix, |
| 5627 | const char *qsuffix, |
| 5628 | struct obj *obj, |
| 5629 | char *(*func)(OBJ_P), |
| 5630 | char *(*altfunc)(OBJ_P), |
| 5631 | const char *lastR) |
| 5632 | { |
| 5633 | char *bufp, *endp; |
| 5634 | /* convert size_t (or int for ancient systems) to ordinary unsigned */ |
| 5635 | unsigned len, lenlimit, |
| 5636 | len_qpfx = (unsigned) (qprefix ? strlen(qprefix) : 0), |
| 5637 | len_qsfx = (unsigned) (qsuffix ? strlen(qsuffix) : 0), |
| 5638 | len_lastR = (unsigned) strlen(lastR); |
| 5639 | |
| 5640 | lenlimit = QBUFSZ - 1; |
| 5641 | endp = qbuf + lenlimit; |
| 5642 | assert(endp != NULL); /* workaround for static analyzer issue */ |
| 5643 | /* sanity check, aimed mainly at paniclog (it's conceivable for |
| 5644 | the result of short_oname() to be shorter than the length of |
| 5645 | the last resort string, but we ignore that possibility here) */ |
| 5646 | if (len_qpfx > lenlimit) |
| 5647 | impossible("safe_qbuf: prefix too long (%u characters).", len_qpfx); |
| 5648 | else if (len_qpfx + len_qsfx > lenlimit) |
| 5649 | impossible("safe_qbuf: suffix too long (%u + %u characters).", |
| 5650 | len_qpfx, len_qsfx); |
| 5651 | else if (len_qpfx + len_lastR + len_qsfx > lenlimit) |
| 5652 | impossible("safe_qbuf: filler too long (%u + %u + %u characters).", |
| 5653 | len_qpfx, len_lastR, len_qsfx); |
| 5654 | |
| 5655 | /* the output buffer might be the same as the prefix if caller |
| 5656 | has already partially filled it */ |
| 5657 | if (qbuf == qprefix) { |
| 5658 | /* prefix is already in the buffer */ |
| 5659 | *endp = '\0'; |
| 5660 | } else if (qprefix) { |
| 5661 | /* put prefix into the buffer */ |
| 5662 | (void) strncpy(qbuf, qprefix, lenlimit); |
| 5663 | *endp = '\0'; |
| 5664 | } else { |
| 5665 | /* no prefix; output buffer starts out empty */ |
| 5666 | qbuf[0] = '\0'; |
| 5667 | } |
| 5668 | len = (unsigned) strlen(qbuf); |
| 5669 | |
| 5670 | if (len + len_lastR + len_qsfx > lenlimit) { |
| 5671 | /* too long; skip formatting, last resort output is truncated */ |
| 5672 | if (len < lenlimit) { |
| 5673 | (void) strncpy(&qbuf[len], lastR, lenlimit - len); |
| 5674 | *endp = '\0'; |
| 5675 | len = (unsigned) strlen(qbuf); |
| 5676 | if (qsuffix && len < lenlimit) { |
| 5677 | (void) strncpy(&qbuf[len], qsuffix, lenlimit - len); |
| 5678 | *endp = '\0'; |
| 5679 | /* len = (unsigned) strlen(qbuf); */ |
| 5680 | } |
no test coverage detected