vis.c (1a2f06d0f2905c9a18340b377cbbe772f2ca6844) vis.c (2f489a509e615c46be6f7c6aa7cea161f50f18af)
1/* $NetBSD: vis.c,v 1.74 2017/11/27 16:37:21 christos Exp $ */
2
3/*-
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 381 unchanged lines hidden (view full) ---

390 * istrsenvisx()
391 * The main internal function.
392 * All user-visible functions call this one.
393 */
394static int
395istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength,
396 int flags, const char *mbextra, int *cerr_ptr)
397{
1/* $NetBSD: vis.c,v 1.74 2017/11/27 16:37:21 christos Exp $ */
2
3/*-
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 381 unchanged lines hidden (view full) ---

390 * istrsenvisx()
391 * The main internal function.
392 * All user-visible functions call this one.
393 */
394static int
395istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength,
396 int flags, const char *mbextra, int *cerr_ptr)
397{
398 char mbbuf[MB_CUR_MAX];
398 wchar_t *dst, *src, *pdst, *psrc, *start, *extra;
399 size_t len, olen;
400 uint64_t bmsk, wmsk;
401 wint_t c;
402 visfun_t f;
403 int clen = 0, cerr, error = -1, i, shft;
399 wchar_t *dst, *src, *pdst, *psrc, *start, *extra;
400 size_t len, olen;
401 uint64_t bmsk, wmsk;
402 wint_t c;
403 visfun_t f;
404 int clen = 0, cerr, error = -1, i, shft;
404 char *mbdst, *mdst;
405 ssize_t mbslength, maxolen;
405 char *mbdst, *mbwrite, *mdst;
406 ssize_t mbslength;
407 size_t maxolen;
406 mbstate_t mbstate;
407
408 _DIAGASSERT(mbdstp != NULL);
409 _DIAGASSERT(mbsrc != NULL || mblength == 0);
410 _DIAGASSERT(mbextra != NULL);
411
412 mbslength = (ssize_t)mblength;
413 /*

--- 122 unchanged lines hidden (view full) ---

536 * If we have hit a multi-byte conversion error on input,
537 * output byte-by-byte here. Else use wctomb().
538 */
539 len = wcslen(start);
540 maxolen = dlen ? *dlen : (wcslen(start) * MB_LEN_MAX + 1);
541 olen = 0;
542 bzero(&mbstate, sizeof(mbstate));
543 for (dst = start; len > 0; len--) {
408 mbstate_t mbstate;
409
410 _DIAGASSERT(mbdstp != NULL);
411 _DIAGASSERT(mbsrc != NULL || mblength == 0);
412 _DIAGASSERT(mbextra != NULL);
413
414 mbslength = (ssize_t)mblength;
415 /*

--- 122 unchanged lines hidden (view full) ---

538 * If we have hit a multi-byte conversion error on input,
539 * output byte-by-byte here. Else use wctomb().
540 */
541 len = wcslen(start);
542 maxolen = dlen ? *dlen : (wcslen(start) * MB_LEN_MAX + 1);
543 olen = 0;
544 bzero(&mbstate, sizeof(mbstate));
545 for (dst = start; len > 0; len--) {
544 if (!cerr)
545 clen = wcrtomb(mbdst, *dst, &mbstate);
546 if (!cerr) {
547 /*
548 * If we have at least MB_CUR_MAX bytes in the buffer,
549 * we'll just do the conversion in-place into mbdst. We
550 * need to be a little more conservative when we get to
551 * the end of the buffer, as we may not have MB_CUR_MAX
552 * bytes but we may not need it.
553 */
554 if (maxolen - olen > MB_CUR_MAX)
555 mbwrite = mbdst;
556 else
557 mbwrite = mbbuf;
558 clen = wcrtomb(mbwrite, *dst, &mbstate);
559 if (clen > 0 && mbwrite != mbdst) {
560 /*
561 * Don't break past our output limit, noting
562 * that maxolen includes the nul terminator so
563 * we can't write past maxolen - 1 here.
564 */
565 if (olen + clen >= maxolen) {
566 errno = ENOSPC;
567 goto out;
568 }
569
570 memcpy(mbdst, mbwrite, clen);
571 }
572 }
546 if (cerr || clen < 0) {
547 /*
548 * Conversion error, process as a byte(s) instead.
549 * Examine each byte and higher-order bytes for
550 * data. E.g.,
551 * 0x000000000000a264 -> a2 64
552 * 0x000000001f00a264 -> 1f 00 a2 64
553 */
554 clen = 0;
555 wmsk = 0;
556 for (i = sizeof(wmsk) - 1; i >= 0; i--) {
557 shft = i * NBBY;
558 bmsk = (uint64_t)0xffLL << shft;
559 wmsk |= bmsk;
573 if (cerr || clen < 0) {
574 /*
575 * Conversion error, process as a byte(s) instead.
576 * Examine each byte and higher-order bytes for
577 * data. E.g.,
578 * 0x000000000000a264 -> a2 64
579 * 0x000000001f00a264 -> 1f 00 a2 64
580 */
581 clen = 0;
582 wmsk = 0;
583 for (i = sizeof(wmsk) - 1; i >= 0; i--) {
584 shft = i * NBBY;
585 bmsk = (uint64_t)0xffLL << shft;
586 wmsk |= bmsk;
560 if ((*dst & wmsk) || i == 0)
587 if ((*dst & wmsk) || i == 0) {
588 if (olen + clen + 1 >= maxolen) {
589 errno = ENOSPC;
590 goto out;
591 }
592
561 mbdst[clen++] = (char)(
562 (uint64_t)(*dst & bmsk) >>
563 shft);
593 mbdst[clen++] = (char)(
594 (uint64_t)(*dst & bmsk) >>
595 shft);
596 }
564 }
565 cerr = 1;
566 }
597 }
598 cerr = 1;
599 }
567 /* If this character would exceed our output limit, stop. */
568 if (olen + clen > (size_t)maxolen)
569 break;
600
601 /*
602 * We'll be dereferencing mbdst[clen] after this to write the
603 * nul terminator; the above paths should have checked for a
604 * possible overflow already.
605 */
606 assert(olen + clen < maxolen);
607
570 /* Advance output pointer by number of bytes written. */
571 mbdst += clen;
572 /* Advance buffer character pointer. */
573 dst++;
574 /* Incrment output character count. */
575 olen += clen;
576 }
577

--- 194 unchanged lines hidden ---
608 /* Advance output pointer by number of bytes written. */
609 mbdst += clen;
610 /* Advance buffer character pointer. */
611 dst++;
612 /* Incrment output character count. */
613 olen += clen;
614 }
615

--- 194 unchanged lines hidden ---