devdraw, acme, snarfer: remove 64KB snarf buffer limit

The snarf code silently dropped text larger than SnarfSize (64KB),
causing paste to produce nothing. Replace the static clip buffer
with a dynamically allocated one, remove all the size checks, and
read the actual X11 property size instead of capping at SnarfSize.
This commit is contained in:
David du Colombier
2026-03-16 21:17:28 +00:00
committed by Dan Cross
parent ae4fdf4268
commit 0d87d4b75e
5 changed files with 48 additions and 39 deletions

View File

@@ -547,10 +547,6 @@ extern void drawsetdebug(int);
/*
* Snarf buffer
*/
enum
{
SnarfSize = 64*1024
};
char *getsnarf(void);
void putsnarf(char*);

View File

@@ -1090,11 +1090,6 @@ iconinit(void)
* fd here rather than use snarffd
*/
/* rio truncates larges snarf buffers, so this avoids using the
* service if the string is huge */
#define MAXSNARF 100*1024
void
acmeputsnarf(void)
{
@@ -1104,8 +1099,6 @@ acmeputsnarf(void)
if(snarfbuf.nc==0)
return;
if(snarfbuf.nc > MAXSNARF)
return;
fmtstrinit(&f);
for(i=0; i<snarfbuf.nc; i+=n){

View File

@@ -1109,7 +1109,7 @@ rpc_getsnarf(void)
void
rpc_putsnarf(char *s)
{
if(s == nil || strlen(s) >= SnarfSize)
if(s == nil)
return;
dispatch_sync(dispatch_get_main_queue(), ^(void) {

View File

@@ -1454,9 +1454,8 @@ rpc_setcursor(Client *client, Cursor *c, Cursor2 *c2)
struct {
QLock lk;
char buf[SnarfSize];
char *buf;
#ifdef APPLESNARF
Rune rbuf[SnarfSize];
PasteboardRef apple;
#endif
} clip;
@@ -1498,7 +1497,7 @@ _xgetsnarffrom(Xwin *w, XWindow xw, Atom clipboard, Atom target, int timeout0, i
/* get the property */
xdata = nil;
XGetWindowProperty(_x.display, w->drawable, prop, 0, SnarfSize/sizeof(ulong), 0,
XGetWindowProperty(_x.display, w->drawable, prop, 0, (len+3)/4, 0,
AnyPropertyType, &type, &fmt, &len, &dummy, &xdata);
if((type != target && type != XA_STRING && type != _x.utf8string) || len == 0){
if(xdata)
@@ -1538,6 +1537,8 @@ rpc_getsnarf(void)
// TODO check more
if(xw == w->drawable){
mine:
data = nil;
if(clip.buf != nil)
data = (uchar*)strdup(clip.buf);
goto out;
}
@@ -1577,12 +1578,11 @@ __xputsnarf(char *data)
XButtonEvent e;
Xwin *w;
if(strlen(data) >= SnarfSize)
return;
qlock(&clip.lk);
xlock();
w = _x.windows;
strcpy(clip.buf, data);
free(clip.buf);
clip.buf = strdup(data);
/* leave note for mouse proc to assert selection ownership */
_x.putsnarf++;
@@ -1627,8 +1627,12 @@ if(0) fprint(2, "xselect target=%d requestor=%d property=%d selection=%d (sizeof
/* text/plain;charset=utf-8 is used by xfce4-terminal 1.0.4 */
/* if the target is STRING we're supposed to reply with Latin1 XXX */
qlock(&clip.lk);
if(clip.buf)
XChangeProperty(_x.display, xe->requestor, xe->property, xe->target,
8, PropModeReplace, (uchar*)clip.buf, strlen(clip.buf));
else
XChangeProperty(_x.display, xe->requestor, xe->property, xe->target,
8, PropModeReplace, (uchar*)"", 0);
qunlock(&clip.lk);
}else{
if(strcmp(name, "TIMESTAMP") != 0)
@@ -1674,6 +1678,8 @@ _applegetsnarf(void)
}
flags = PasteboardSynchronize(clip.apple);
if(flags&kPasteboardClientIsOwner){
s = nil;
if(clip.buf != nil)
s = strdup(clip.buf);
qunlock(&clip.lk);
return s;
@@ -1716,14 +1722,21 @@ _appleputsnarf(char *s)
{
CFDataRef cfdata;
PasteboardSyncFlags flags;
Rune *r;
int n;
/* fprint(2, "appleputsnarf\n"); */
if(strlen(s) >= SnarfSize)
return;
qlock(&clip.lk);
strcpy(clip.buf, s);
runesnprint(clip.rbuf, nelem(clip.rbuf), "%s", s);
free(clip.buf);
clip.buf = strdup(s);
n = utflen(s) + 1;
r = malloc(n * sizeof(Rune));
if(r == nil){
qunlock(&clip.lk);
return;
}
runesnprint(r, n, "%s", s);
if(clip.apple == nil){
if(PasteboardCreate(kPasteboardClipboard, &clip.apple) != noErr){
fprint(2, "apple pasteboard create failed\n");
@@ -1733,17 +1746,20 @@ _appleputsnarf(char *s)
}
if(PasteboardClear(clip.apple) != noErr){
fprint(2, "apple pasteboard clear failed\n");
free(r);
qunlock(&clip.lk);
return;
}
flags = PasteboardSynchronize(clip.apple);
if((flags&kPasteboardModified) || !(flags&kPasteboardClientIsOwner)){
fprint(2, "apple pasteboard cannot assert ownership\n");
free(r);
qunlock(&clip.lk);
return;
}
cfdata = CFDataCreate(kCFAllocatorDefault,
(uchar*)clip.rbuf, runestrlen(clip.rbuf)*2);
(uchar*)r, runestrlen(r)*2);
free(r);
if(cfdata == nil){
fprint(2, "apple pasteboard cfdatacreate failed\n");
qunlock(&clip.lk);

View File

@@ -54,11 +54,8 @@ AUTOFRAMEWORK(Carbon)
#undef time
AUTOLIB(draw) /* to cause link of X11 */
enum {
SnarfSize = 65536
};
char snarf[3*SnarfSize+1];
Rune rsnarf[SnarfSize+1];
char *snarf;
Rune *rsnarf;
XDisplay *xdisplay;
XWindow drawable;
Atom xclipboard;
@@ -98,6 +95,7 @@ main(int argc, char **argv)
break;
}ARGEND
snarf = strdup("");
if((xdisplay = XOpenDisplay(nil)) == nil)
sysfatal("XOpenDisplay: %r");
drawable = XCreateWindow(xdisplay, DefaultRootWindow(xdisplay),
@@ -256,18 +254,16 @@ xgetsnarf(void)
return nil;
/* get the property */
data = nil;
XGetWindowProperty(xd, drawable, prop, 0, SnarfSize/sizeof(ulong), 0,
XGetWindowProperty(xd, drawable, prop, 0, (len+3)/4, 0,
AnyPropertyType, &type, &fmt, &len, &dummy, &xdata);
if(xdata == nil || (type != XA_STRING && type != xutf8string) || len == 0){
if(xdata)
XFree(xdata);
return nil;
}
if(strlen((char*)xdata) >= SnarfSize){
free(snarf);
snarf = strdup((char*)xdata);
XFree(xdata);
return nil;
}
strcpy(snarf, (char*)xdata);
return snarf;
}
@@ -286,8 +282,16 @@ appleputsnarf(void)
#ifdef __APPLE__
CFDataRef cfdata;
PasteboardSyncFlags flags;
int n;
runesnprint(rsnarf, nelem(rsnarf), "%s", snarf);
if(snarf == nil)
return;
n = utflen(snarf) + 1;
free(rsnarf);
rsnarf = malloc(n * sizeof(Rune));
if(rsnarf == nil)
return;
runesnprint(rsnarf, n, "%s", snarf);
if(PasteboardClear(appleclip) != noErr){
fprint(2, "apple pasteboard clear failed\n");
return;