1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-24 06:54:13 +00:00
cde/src/cmd/ksh93/sh/fcin.c
Martijn Dekker 781f0a39aa Fix parsing of multibyte characters
According to Red Hat, this fixes "a bug on input buffer boundary
and/or temporary composing buffer of multibyte characters".
The patch was credited to Paulo Andrade <pandrade@redhat.com>.

To be honest, I don't know how to trigger this bug or what the code
removed by this fix really does, but this patch is in production
use at Red Hat, removes some smelly stuff, and is not triggering
any regression test failures, so I'll just take this one on faith.

https://bugzilla.redhat.com/show_bug.cgi?id=1417886
https://github.com/att/ast/commit/4fa2020b

src/cmd/ksh93/sh/fcin.c:
- _fcmbget(): Remove some dodgy-looking buffer-fiddling code that
  is marked as "for testing purposes with small buffers".

(cherry picked from commit 407760fdbddcb7f8ac92b5d1da29d3e09dac0369)
2020-06-12 01:45:17 +02:00

170 lines
4.1 KiB
C

/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1982-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* http://www.eclipse.org/org/documents/epl-v10.html *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* David Korn <dgk@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Routines to implement fast character input
*
* David Korn
* AT&T Labs
*
*/
#include <ast.h>
#include <sfio.h>
#include <error.h>
#include <fcin.h>
Fcin_t _Fcin = {0};
/*
* open stream <f> for fast character input
*/
int fcfopen(register Sfio_t* f)
{
register int n;
char *buff;
Fcin_t save;
errno = 0;
_Fcin.fcbuff = _Fcin.fcptr;
_Fcin._fcfile = f;
fcsave(&save);
if(!(buff=(char*)sfreserve(f,SF_UNBOUND,SF_LOCKR)))
{
fcrestore(&save);
_Fcin.fcchar = 0;
_Fcin.fcptr = _Fcin.fcbuff = &_Fcin.fcchar;
_Fcin.fclast = 0;
_Fcin._fcfile = (Sfio_t*)0;
return(EOF);
}
n = sfvalue(f);
fcrestore(&save);
sfread(f,buff,0);
_Fcin.fcoff = sftell(f);;
buff = (char*)sfreserve(f,SF_UNBOUND,SF_LOCKR);
_Fcin.fclast = (_Fcin.fcptr=_Fcin.fcbuff=(unsigned char*)buff)+n;
if(sffileno(f) >= 0)
*_Fcin.fclast = 0;
return(n);
}
/*
* With _Fcin.fcptr>_Fcin.fcbuff, the stream pointer is advanced and
* If _Fcin.fclast!=0, performs an sfreserve() for the next buffer.
* If a notify function has been set, it is called
* If last is non-zero, and the stream is a file, 0 is returned when
* the previous character is a 0 byte.
*/
int fcfill(void)
{
register int n;
register Sfio_t *f;
register unsigned char *last=_Fcin.fclast, *ptr=_Fcin.fcptr;
if(!(f=fcfile()))
{
/* see whether pointer has passed null byte */
if(ptr>_Fcin.fcbuff && *--ptr==0)
_Fcin.fcptr=ptr;
else
_Fcin.fcoff = 0;
return(0);
}
if(last)
{
if( ptr<last && ptr>_Fcin.fcbuff && *(ptr-1)==0)
return(0);
if(_Fcin.fcchar)
*last = _Fcin.fcchar;
if(ptr > last)
_Fcin.fcptr = ptr = last;
}
if((n = ptr-_Fcin.fcbuff) && _Fcin.fcfun)
(*_Fcin.fcfun)(f,(const char*)_Fcin.fcbuff,n,_Fcin.context);
sfread(f, (char*)_Fcin.fcbuff, n);
_Fcin.fcoff +=n;
_Fcin._fcfile = 0;
if(!last)
return(0);
else if(fcfopen(f) < 0)
return(EOF);
return(*_Fcin.fcptr++);
}
/*
* Synchronize and close the current stream
*/
int fcclose(void)
{
register unsigned char *ptr;
if(_Fcin.fclast==0)
return(0);
if((ptr=_Fcin.fcptr)>_Fcin.fcbuff && *(ptr-1)==0)
_Fcin.fcptr--;
if(_Fcin.fcchar)
*_Fcin.fclast = _Fcin.fcchar;
_Fcin.fclast = 0;
_Fcin.fcleft = 0;
return(fcfill());
}
/*
* Set the notify function that is called for each fcfill()
*/
void fcnotify(void (*fun)(Sfio_t*,const char*,int,void*),void* context)
{
_Fcin.fcfun = fun;
_Fcin.context = context;
}
#ifdef __EXPORT__
# define extern __EXPORT__
#endif
#undef fcsave
extern void fcsave(Fcin_t *fp)
{
*fp = _Fcin;
}
#undef fcrestore
extern void fcrestore(Fcin_t *fp)
{
_Fcin = *fp;
}
int _fcmbget(short *len)
{
register int c;
switch(*len = mbsize(_Fcin.fcptr))
{
case -1:
*len = 1;
/* fall through */
case 0:
case 1:
c=fcget();
break;
default:
c = mbchar(_Fcin.fcptr);
}
return(c);
}