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 --- |