diff options
author | itojun <itojun@pkgsrc.org> | 2002-12-02 03:40:20 +0000 |
---|---|---|
committer | itojun <itojun@pkgsrc.org> | 2002-12-02 03:40:20 +0000 |
commit | 14a52881764d8a78312fa365d0fa3a36e562f64f (patch) | |
tree | 2b17cced6fea9137013bd6291e5465691afd4630 /inputmethod | |
parent | d4b0776acefa2e9a011beb9597db5c2cc3867585 (diff) | |
download | pkgsrc-14a52881764d8a78312fa365d0fa3a36e562f64f.tar.gz |
apply point patch to solve remote buffer overrun vuln.
(should upgrade to 3.6p1)
http://canna.sourceforge.jp/sec/Canna-2002-01.txt
Diffstat (limited to 'inputmethod')
-rw-r--r-- | inputmethod/canna-lib/distinfo | 5 | ||||
-rw-r--r-- | inputmethod/canna-lib/patches/patch-ag | 360 | ||||
-rw-r--r-- | inputmethod/canna-lib/patches/patch-ah | 26 | ||||
-rw-r--r-- | inputmethod/canna-lib/patches/patch-ai | 33 | ||||
-rw-r--r-- | inputmethod/canna-server-bin/Makefile | 4 | ||||
-rw-r--r-- | inputmethod/canna-server/Makefile | 6 |
6 files changed, 428 insertions, 6 deletions
diff --git a/inputmethod/canna-lib/distinfo b/inputmethod/canna-lib/distinfo index 10f618fe040..c7abfa069ee 100644 --- a/inputmethod/canna-lib/distinfo +++ b/inputmethod/canna-lib/distinfo @@ -1,4 +1,4 @@ -$NetBSD: distinfo,v 1.3 2002/08/25 19:22:55 jlam Exp $ +$NetBSD: distinfo,v 1.4 2002/12/02 03:40:20 itojun Exp $ SHA1 (Uum4.109.tar.gz) = 9d57fa67fc321c0b1101970b02154b5d6e42e88e Size (Uum4.109.tar.gz) = 43738 bytes @@ -16,3 +16,6 @@ SHA1 (patch-ac) = 8f9f999eb8abd9c8e3d3e5c66cf55150ce700919 SHA1 (patch-ad) = dd2eb94e75dc4789e298aa1601280d32fbe5ec96 SHA1 (patch-ae) = e44c60ddf1e042ab5df1457b6723071c38baae02 SHA1 (patch-af) = 2700fc8395895176c16562af66ea5bf0b13d4e10 +SHA1 (patch-ag) = 5436f27d2f5fff1d317d58b3beeb1233d801ef32 +SHA1 (patch-ah) = eee6fc00787dbb59fd7571ba09cbed28c5c18e9c +SHA1 (patch-ai) = 77cc19926b80f503c9b5171e10722ed0a492dec4 diff --git a/inputmethod/canna-lib/patches/patch-ag b/inputmethod/canna-lib/patches/patch-ag new file mode 100644 index 00000000000..80704c72cb1 --- /dev/null +++ b/inputmethod/canna-lib/patches/patch-ag @@ -0,0 +1,360 @@ +$NetBSD: patch-ag,v 1.1 2002/12/02 03:40:21 itojun Exp $ + +security fix between 3.6 -> 3.6p1 + +--- server/wconvert.c.orig Wed Nov 27 16:27:28 1996 ++++ server/wconvert.c Sat Nov 9 10:38:45 2002 +@@ -100,6 +100,7 @@ + #endif + + extern void DispDebug() ; ++extern const Ushort *ushortmemchr pro((const Ushort *, int, size_t)); + extern int canna_server_hi ; + extern int canna_server_lo ; + #ifdef DEBUG +@@ -1322,7 +1323,10 @@ + char *dirname, *dirnamelong = (char *)0; + int cxnum = Request.type18.context, stat = -1; + int requestsize = Request.type18.size, retval; ++ size_t datasize = Request.type18.datalen - SIZEOFSHORT * 2; + ++ if (datasize == 0 || req->data[datasize - 1] != 0) ++ goto protoerr; + if (validcontext(cxnum, client, wListDictionary)) { + if (requestsize <= sizeof(local_buffer) || + (dicnames = malloc(requestsize))) { +@@ -1359,6 +1363,7 @@ + } + } + ++protoerr: + retval = SendType6Reply(client, wListDictionary, EXTPROTO, stat, + dicnames, namesize(dicnames, stat)); + if (dicnames != (char *)local_buffer) free(dicnames); +@@ -1470,10 +1475,15 @@ + char *dicname, *dirname, *dirnamelong = (char *)0; + int cxnum = Request.type18.context, stat = BADCONT; + int dirlen, requestsize = Request.type18.size, retval; ++ size_t datasize = Request.type18.datalen - SIZEOFSHORT * 2; + ++ if (datasize == 0 || req->data[datasize - 1] != 0) ++ goto protoerr; + if (validcontext(cxnum, client, wGetWordTextDictionary)) { + dirname = req->data ; + dirlen = strlen(dirname) + 1 ; ++ if (dirlen == datasize) ++ goto protoerr; + dicname = &(req->data[dirlen]) ; + if (dirlen > 1) { + if (!dirname || dirname[0] != ':' || +@@ -1515,6 +1525,7 @@ + free(dirnamelong); + } + } ++protoerr: + retval = SendType7Reply(client, wGetWordTextDictionary, EXTPROTO, + stat, stat > 0 ? stat + 1 : 0, infobuf); + if (infobuf != (Ushort *)local_buffer) free((char *)infobuf); +@@ -2296,6 +2307,9 @@ + { + ir_debug( Dmsg(10, "ProcWideReq1 start!!\n") ); + ++ if (Request.type1.datalen != 0) ++ return( -1 ); ++ + return( 0 ) ; + } + +@@ -2305,6 +2319,8 @@ + { + ir_debug( Dmsg(10, "ProcWideReq2 start!!\n") ); + ++ if (Request.type2.datalen != SIZEOFSHORT) ++ return( -1 ); + buf += HEADER_SIZE; Request.type2.context = S2TOS(buf); + ir_debug( Dmsg(10, "req->context =%d\n", Request.type2.context) ); + +@@ -2317,6 +2333,8 @@ + { + ir_debug( Dmsg(10, "ProcWideReq3 start!!\n") ); + ++ if (Request.type3.datalen != SIZEOFSHORT * 2) ++ return( -1 ); + buf += HEADER_SIZE; Request.type3.context = S2TOS(buf); + buf += SIZEOFSHORT; Request.type3.buflen = S2TOS(buf); + ir_debug( Dmsg(10, "req->context =%d\n", Request.type3.context) ); +@@ -2334,12 +2352,18 @@ + + ir_debug( Dmsg(10, "ProcWideReq4 start!!\n") ); + ++ if (Request.type4.datalen < SIZEOFSHORT * 4) ++ return( -1 ); + buf += HEADER_SIZE; Request.type4.context = S2TOS(buf); + buf += SIZEOFSHORT; Request.type4.begin = S2TOS(buf); + buf += SIZEOFSHORT; Request.type4.end = S2TOS(buf); + buf += SIZEOFSHORT; Request.type4.yomilen = S2TOS(buf); + Request.type4.yomi = (Ushort *)(buf += SIZEOFSHORT) ; +- len = Request.type4.datalen - SIZEOFSHORT * 4; ++ len = Request.type4.yomilen + 1; ++ if (Request.type4.datalen != SIZEOFSHORT * (4 + len) ++ || len == 0 ++ || Request.type4.yomi[len - 1] != 0) ++ return( -1 ); + for (data = Request.type4.yomi, i = 0; i < len; i++, data++) + *data = ntohs((unsigned short)*data); /* ちょっとやだなあ */ + ir_debug( Dmsg(10, "req->context =%d\n", Request.type4.context) ); +@@ -2359,6 +2383,8 @@ + { + ir_debug( Dmsg(10, "ProcWideReq5 start!!\n") ); + ++ if (Request.type5.datalen != SIZEOFSHORT * 2 + SIZEOFINT) ++ return( -1 ); + buf += HEADER_SIZE; Request.type5.context = S2TOS(buf); + buf += SIZEOFSHORT; Request.type5.size = S2TOS(buf); + buf += SIZEOFSHORT; Request.type5.mode = L4TOL(buf); +@@ -2375,6 +2401,8 @@ + { + ir_debug( Dmsg(10, "ProcWideReq6 start!!\n") ); + ++ if (Request.type6.datalen != SIZEOFSHORT * 3) ++ return( -1 ); + buf += HEADER_SIZE; Request.type6.context = S2TOS(buf); + buf += SIZEOFSHORT; Request.type6.number = S2TOS(buf); + buf += SIZEOFSHORT; Request.type6.buflen = S2TOS(buf); +@@ -2391,6 +2419,8 @@ + { + ir_debug( Dmsg(10, "ProcWideReq7 start!!\n") ); + ++ if (Request.type7.datalen != SIZEOFSHORT * 3) ++ return( -1 ); + buf += HEADER_SIZE; Request.type7.context = S2TOS(buf); + buf += SIZEOFSHORT; Request.type7.number = S2TOS(buf); + buf += SIZEOFSHORT; Request.type7.yomilen = (short)S2TOS(buf); +@@ -2407,6 +2437,8 @@ + { + ir_debug( Dmsg(10, "ProcWideReq8 start!!\n") ); + ++ if (Request.type8.datalen != SIZEOFSHORT * 4) ++ return( -1 ); + buf += HEADER_SIZE; Request.type8.context = S2TOS(buf); + buf += SIZEOFSHORT; Request.type8.curbun = S2TOS(buf); + buf += SIZEOFSHORT; Request.type8.curkouho = S2TOS(buf); +@@ -2425,6 +2457,8 @@ + { + ir_debug( Dmsg(10, "ProcWideReq9 start!!\n") ); + ++ if (Request.type9.datalen != SIZEOFSHORT * 4) ++ return( -1 ); + buf += HEADER_SIZE; Request.type9.context = S2TOS(buf); + buf += SIZEOFSHORT; Request.type9.number = S2TOS(buf); + buf += SIZEOFSHORT; Request.type9.kouho = S2TOS(buf); +@@ -2442,9 +2476,13 @@ + BYTE *buf ; + { + register int i ; ++ int rest; + + ir_debug( Dmsg(10, "ProcWideReq10 start!!\n") ); + ++ rest = Request.type10.datalen - (SIZEOFSHORT * 2 + SIZEOFINT); ++ if (rest < 0) ++ return( -1 ); + buf += HEADER_SIZE; Request.type10.context = S2TOS(buf); + buf += SIZEOFSHORT; Request.type10.number = S2TOS(buf); + buf += SIZEOFSHORT; Request.type10.mode = L4TOL(buf); +@@ -2452,6 +2490,8 @@ + ir_debug( Dmsg(10, "req->number =%d\n", Request.type10.number) ); + ir_debug( Dmsg(10, "req->mode =%d\n", Request.type10.mode) ); + ++ if (rest != Request.type10.number * SIZEOFSHORT) ++ return( -1 ); + buf += SIZEOFINT; Request.type10.kouho = (short *)buf; /* short? */ + for (i = 0; i < Request.type10.number; i++) { + Request.type10.kouho[i] = S2TOS(buf); buf += SIZEOFSHORT; +@@ -2468,12 +2508,18 @@ + register Ushort *data; + int i, len ; + +- ir_debug( Dmsg(10, "ProcWideReq10 start!!\n") ); ++ ir_debug( Dmsg(10, "ProcWideReq11 start!!\n") ); + ++ if (Request.type11.datalen < SIZEOFSHORT * 2) ++ return( -1 ); + buf += HEADER_SIZE; Request.type11.context = S2TOS(buf); + buf += SIZEOFSHORT; Request.type11.curbun = S2TOS(buf); + buf += SIZEOFSHORT; Request.type11.yomi = (Ushort *)buf; ++ if (Request.type11.datalen % SIZEOFSHORT != 0) ++ return( -1 ); + len = ((int)Request.type11.datalen - SIZEOFSHORT * 2) / SIZEOFSHORT ; ++ if (len == 0 || Request.type11.yomi[len - 1] != 0) ++ return( -1 ); + for (data = Request.type11.yomi, i = 0; i < len; i++, data++) + *data = ntohs( *data ); /* なんかやだ */ + ir_debug( Dmsg(10, "req->context =%d\n", Request.type11.context) ); +@@ -2490,16 +2536,26 @@ + BYTE *buf ; + { + register Ushort *data; +- int i, len ; ++ int i, len, rest ; + + ir_debug( Dmsg(10, "ProcWideReq12 start!!\n") ); + ++ rest = Request.type12.datalen - SIZEOFSHORT; ++ if (rest < 0) ++ return( -1 ); + buf += HEADER_SIZE; Request.type12.context = S2TOS(buf); + buf += SIZEOFSHORT; Request.type12.datainfo = (Ushort *)buf; ++ if (!ushortmemchr((Ushort *)buf, 0, rest / SIZEOFSHORT)) ++ return( -1 ); + len = ushortstrlen((Ushort *)buf) + 1; ++ rest -= len * SIZEOFSHORT; ++ if (rest <= 0) ++ return( -1 ); + for( data = Request.type12.datainfo, i = 0; i < len; i++, data++ ) + *data = ntohs( *data ); /* なんかやだ */ + buf += len * SIZEOFSHORT; ++ if (buf[rest - 1] != '\0') ++ return( -1 ); + Request.type12.dicname = (char *)buf; + ir_debug( Dmsg(10, "req->context =%d\n", Request.type12.context) ); + ir_debug( Dmsg(10, "req->datainfo =%s\n", +@@ -2517,24 +2573,37 @@ + BYTE *buf ; + { + register Ushort *data; +- int i ,len ; ++ int i ,len, rest; + + ir_debug( Dmsg(10, "ProcWideReq13 start!!\n") ); + ++ rest = Request.type13.datalen - SIZEOFSHORT; ++ if (rest < 0) ++ return( -1 ); + buf += HEADER_SIZE; Request.type13.context = S2TOS(buf); + len = SIZEOFSHORT ; + buf += len; + Request.type13.dicname = (char *)buf; ++ if (!memchr(buf, 0, rest)) ++ return( -1 ); + len = strlen( (char *)buf ) + 1; ++ rest -= len; ++ if (rest % SIZEOFSHORT ++ || rest < SIZEOFSHORT * 3) ++ return( -1 ); + buf += len; + Request.type13.yomi = (Ushort *)buf; + len = ((int)Request.type13.datalen - len - SIZEOFSHORT * 4) / SIZEOFSHORT; ++ if (ushortmemchr((Ushort *)buf, 0, len) != (Ushort *)buf + len - 1) ++ return( -1 ); + for( data = Request.type13.yomi, i = 0; i < len; i++, data++) + *data = ntohs( *data ); +- buf += (ushortstrlen((Ushort *)buf) + 1) * SIZEOFSHORT; ++ buf += len * SIZEOFSHORT; + Request.type13.yomilen = S2TOS(buf); + buf += SIZEOFSHORT; Request.type13.kouhosize = S2TOS(buf); + buf += SIZEOFSHORT; Request.type13.hinshisize = S2TOS(buf); ++ if (Request.type13.yomilen != len - 1) ++ return( -1 ); + ir_debug( Dmsg(10, "req->context =%d\n", Request.type13.context) ); + ir_debug( Dmsg(10, "req->dicname =%s\n", Request.type13.dicname) ); + ir_debug( Dmsg(10, "req->yomi =%s\n", +@@ -2556,11 +2625,16 @@ + + ir_debug( Dmsg(10, "ProcWideReq14 start!!\n") ); + ++ if (Request.type14.datalen <= SIZEOFINT + SIZEOFSHORT ++ || Request.type14.datalen % SIZEOFSHORT) ++ return( -1 ); + buf += HEADER_SIZE; Request.type14.mode = L4TOL(buf); + buf += SIZEOFINT; Request.type14.context = S2TOS(buf); + buf += SIZEOFSHORT; Request.type14.yomi = (Ushort *)buf; + len = ((int)Request.type14.datalen - SIZEOFSHORT - SIZEOFINT) + / SIZEOFSHORT; ++ if (Request.type14.yomi[len - 1] != 0) ++ return( -1 ); + for (data = Request.type14.yomi, i = 0; i < len; i++, data++) + *data = ntohs( *data ); /* なんかやだ */ + +@@ -2577,11 +2651,17 @@ + ProcWideReq15(buf) + BYTE *buf ; + { ++ int rest; + ir_debug( Dmsg(10, "ProcWideReq15 start!!\n") ); + ++ rest = Request.type15.datalen - (SIZEOFINT + SIZEOFSHORT); ++ if (rest <= 0) ++ return( -1 ); + buf += HEADER_SIZE; Request.type15.mode = L4TOL(buf); + buf += SIZEOFINT; Request.type15.context = S2TOS(buf); + buf += SIZEOFSHORT; Request.type15.dicname = (char *)buf; ++ if (buf[rest - 1] != 0) ++ return( -1 ); + ir_debug( Dmsg(10, "req->mode =%d\n", Request.type15.mode) ); + ir_debug( Dmsg(10, "req->context =%d\n", Request.type15.context) ); + ir_debug( Dmsg(10, "req->dicname =%s\n", +@@ -2597,6 +2677,9 @@ + ir_debug( Dmsg(10, "ProcWideReq17 start!!\n") ); + + buf += HEADER_SIZE; ++ if (Request.type17.datalen < SIZEOFCHAR * 2 ++ || buf[Request.type17.datalen - SIZEOFCHAR * 2] != 0) ++ return( -1 ); + Request.type17.dicname = (char *)buf; + Request.type17.mode = (char)*(buf + Request.type17.datalen - SIZEOFCHAR) ; + ir_debug( Dmsg(10, "req->dicname =%s\n", +@@ -2613,6 +2696,8 @@ + { + ir_debug( Dmsg(10, "ProcWideReq18 start!!\n") ); + ++ if (Request.type18.datalen < SIZEOFSHORT * 2) ++ return( -1 ); + buf += HEADER_SIZE; Request.type18.context = S2TOS(buf); + buf += SIZEOFSHORT; Request.type18.data = (char *)buf; + buf += Request.type18.datalen - SIZEOFSHORT * 2; +@@ -2630,12 +2715,18 @@ + ProcWideReq19(buf) + BYTE *buf ; + { ++ int rest; + ir_debug( Dmsg(10, "ProcWideReq19 start!!\n") ); + ++ rest = Request.type20.datalen - (SIZEOFSHORT + SIZEOFINT * 2); ++ if (rest < 0) ++ return( -1 ); + buf += HEADER_SIZE; Request.type20.context = S2TOS(buf); + buf += SIZEOFSHORT; Request.type20.command = L4TOL(buf); + buf += SIZEOFINT; Request.type20.bufsize = L4TOL(buf); + buf += SIZEOFINT; Request.type20.buf = (char *)buf; ++ if (Request.type20.bufsize != rest) ++ return( -1 ); + ir_debug( Dmsg(10, "req->context =%d\n", Request.type20.context) ); + ir_debug( Dmsg(10, "req->command =%d\n", Request.type20.command) ); + ir_debug( Dmsg(10, "req->bufsize =%d\n", Request.type20.bufsize) ); +@@ -2647,15 +2738,25 @@ + ProcWideReq20(buf) + BYTE *buf ; + { ++ BYTE *bufend; + ir_debug( Dmsg(10, "ProcWideReq20 start!!\n") ); + ++ if (Request.type21.datalen < SIZEOFINT + SIZEOFSHORT) ++ return( -1 ); + buf += HEADER_SIZE; Request.type21.mode = L4TOL(buf); ++ bufend = buf + Request.type21.datalen; + buf += SIZEOFINT; Request.type21.context = S2TOS(buf); + buf += SIZEOFSHORT; Request.type21.dirname = (char *)buf; ++ if (!memchr(buf, 0, bufend - buf)) ++ return( -1 ); + buf += strlen((char *)buf) + 1; + Request.type21.srcdic = (char *)buf; ++ if (!memchr(buf, 0, bufend - buf)) ++ return( -1 ); + buf += strlen((char *)buf) + 1; + Request.type21.dstdic = (char *)buf; ++ if (*(bufend - 1) != 0) ++ return( -1 ); + + ir_debug( Dmsg(10, "req->mode =%d\n", Request.type21.mode) ); + ir_debug( Dmsg(10, "req->context =%d\n", Request.type21.context) ); diff --git a/inputmethod/canna-lib/patches/patch-ah b/inputmethod/canna-lib/patches/patch-ah new file mode 100644 index 00000000000..f1d38c835d4 --- /dev/null +++ b/inputmethod/canna-lib/patches/patch-ah @@ -0,0 +1,26 @@ +$NetBSD: patch-ah,v 1.1 2002/12/02 03:40:21 itojun Exp $ + +security fix between 3.6 -> 3.6p1 + +--- server/util.c.orig Wed Nov 6 19:09:47 1996 ++++ server/util.c Sat Nov 9 10:39:17 2002 +@@ -217,6 +217,19 @@ + return res; + } + ++const Ushort * ++ushortmemchr(ws, ch, len) ++const Ushort *ws; ++int ch; ++size_t len; ++{ ++ const Ushort *p, *end; ++ for (p = ws, end = ws + len; p < end; ++p) ++ if (*p == (Ushort)ch) ++ return p; ++ return NULL; ++} ++ + int + ushortstrcpy(wd, ws) + Ushort *wd, *ws; diff --git a/inputmethod/canna-lib/patches/patch-ai b/inputmethod/canna-lib/patches/patch-ai new file mode 100644 index 00000000000..154b178c42b --- /dev/null +++ b/inputmethod/canna-lib/patches/patch-ai @@ -0,0 +1,33 @@ +$NetBSD: patch-ai,v 1.1 2002/12/02 03:40:21 itojun Exp $ + +security fix between 3.6 -> 3.6p1 + +--- server/convert.c.orig Mon Dec 2 20:01:34 1996 ++++ server/convert.c Sat Nov 9 10:39:32 2002 +@@ -53,6 +53,8 @@ + #define ACK2 2 + #define ACK3 3 + #define CHECK_ACK_BUF_SIZE (ACK_BUFSIZE + (SIZEOFLONG * 2) ) ++#define IR_INT_MAX 32767 ++#define IR_INT_INVAL(x) ((unsigned int)x > IR_INT_MAX) + + extern int errno; + +@@ -1778,6 +1780,8 @@ + return( needsize ) ; + + req->namelen = (int)L4TOL(buf + SIZE4); ++ if( IR_INT_INVAL(req->namelen) ) ++ return( -1 ); + ir_debug( Dmsg(10,"req->namelen =%d\n", req->namelen ); ) + + if( (needsize = SIZE8 + req->namelen - size) > 0 ) +@@ -1785,6 +1789,8 @@ + + if( req->namelen > 0 ){ + req->name = buf + SIZE8 ; ++ if( req->name[req->namelen - 1] != 0 ) ++ return( -1 ); + } + ir_debug( Dmsg(10,"req->namelen =%d\n", req->namelen ); ) + ir_debug( Dmsg(10,"req->name =%s\n", req->name ); ) diff --git a/inputmethod/canna-server-bin/Makefile b/inputmethod/canna-server-bin/Makefile index f45be51817a..87dfc7d195b 100644 --- a/inputmethod/canna-server-bin/Makefile +++ b/inputmethod/canna-server-bin/Makefile @@ -1,8 +1,8 @@ -# $NetBSD: Makefile,v 1.2 2002/10/25 17:04:09 wiz Exp $ +# $NetBSD: Makefile,v 1.3 2002/12/02 03:40:21 itojun Exp $ DISTNAME= Canna35b2 PKGNAME= Canna-server-bin-3.5.2 -PKGREVISION= 2 +PKGREVISION= 3 CATEGORIES= japanese inputmethod MASTER_SITES= ftp://ftp.nec.co.jp/pub/Canna/Canna35/ diff --git a/inputmethod/canna-server/Makefile b/inputmethod/canna-server/Makefile index 10c85662ede..61702ee9906 100644 --- a/inputmethod/canna-server/Makefile +++ b/inputmethod/canna-server/Makefile @@ -1,7 +1,7 @@ -# $NetBSD: Makefile,v 1.2 2002/06/10 09:52:15 sakamoto Exp $ +# $NetBSD: Makefile,v 1.3 2002/12/02 03:40:21 itojun Exp $ DISTNAME= Canna-server-3.5.2 -PKGREVISION= 2 +PKGREVISION= 3 CATEGORIES= japanese inputmethod MASTER_SITES= # empty DISTFILES= # empty @@ -9,7 +9,7 @@ DISTFILES= # empty MAINTAINER= tech-pkg-ja@jp.netbsd.org COMMENT= Kana-Kanji conversion system (server) -DEPENDS+= Canna-server-bin>=3.5.2nb2:../canna-server-bin +DEPENDS+= Canna-server-bin>=3.5.2nb3:../canna-server-bin DEPENDS+= Canna-dict>=3.5.2nb2:../canna-dict EXTRACT_ONLY= # empty |