summaryrefslogtreecommitdiffstats
path: root/source/lib
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>1998-05-12 00:55:32 +0000
committerJeremy Allison <jra@samba.org>1998-05-12 00:55:32 +0000
commit2d774454005f0b54e5684cf618da7060594dfcbb (patch)
treed3e7831d1d5eb0cc21a78dadb51d63a82c269d2d /source/lib
parentc760ebbf127796427c4602aae61952df938c6def (diff)
downloadsamba-2d774454005f0b54e5684cf618da7060594dfcbb.tar.gz
samba-2d774454005f0b54e5684cf618da7060594dfcbb.tar.xz
samba-2d774454005f0b54e5684cf618da7060594dfcbb.zip
This is a security audit change of the main source.
It removed all ocurrences of the following functions : sprintf strcpy strcat The replacements are slprintf, safe_strcpy and safe_strcat. It should not be possible to use code in Samba that uses sprintf, strcpy or strcat, only the safe_equivalents. Once Andrew has fixed the slprintf implementation then this code will be moved back to the 1.9.18 code stream. Jeremy.
Diffstat (limited to 'source/lib')
-rw-r--r--source/lib/charset.c6
-rw-r--r--source/lib/genrand.c2
-rw-r--r--source/lib/kanji.c26
-rw-r--r--source/lib/pidfile.c2
-rw-r--r--source/lib/slprintf.c8
-rw-r--r--source/lib/time.c2
-rw-r--r--source/lib/util.c190
7 files changed, 152 insertions, 84 deletions
diff --git a/source/lib/charset.c b/source/lib/charset.c
index d8ce38f3968..db331af115d 100644
--- a/source/lib/charset.c
+++ b/source/lib/charset.c
@@ -200,9 +200,9 @@ static codepage_p load_client_codepage( int client_codepage )
return NULL;
}
- strcpy(codepage_file_name, CODEPAGEDIR);
- strcat(codepage_file_name, "/");
- strcat(codepage_file_name, "codepage.");
+ pstrcpy(codepage_file_name, CODEPAGEDIR);
+ pstrcat(codepage_file_name, "/");
+ pstrcat(codepage_file_name, "codepage.");
slprintf(&codepage_file_name[strlen(codepage_file_name)],
sizeof(pstring)-(strlen(codepage_file_name)+1),
"%03d",
diff --git a/source/lib/genrand.c b/source/lib/genrand.c
index b09f683e62d..5e87275ce89 100644
--- a/source/lib/genrand.c
+++ b/source/lib/genrand.c
@@ -84,7 +84,7 @@ static void do_dirrand(char *name, unsigned char *buf, int buf_len)
struct stat st;
if(strlen(p) <= len_left)
- strcpy(pos, p);
+ pstrcpy(pos, p);
if(sys_stat(fullname,&st) == 0) {
SIVAL(buf, ((counter * 4)%(buf_len-4)),
diff --git a/source/lib/kanji.c b/source/lib/kanji.c
index 401e91e5349..afe255d36a4 100644
--- a/source/lib/kanji.c
+++ b/source/lib/kanji.c
@@ -419,7 +419,7 @@ static char *sj_to_euc(char *from, BOOL overwrite)
}
*out = 0;
if (overwrite) {
- strcpy((char *) save, (char *) cvtbuf);
+ pstrcpy((char *) save, (char *) cvtbuf);
return (char *) save;
} else {
return cvtbuf;
@@ -451,7 +451,7 @@ static char *euc_to_sj(char *from, BOOL overwrite)
}
*out = 0;
if (overwrite) {
- strcpy(save, (char *) cvtbuf);
+ pstrcpy(save, (char *) cvtbuf);
return save;
} else {
return cvtbuf;
@@ -522,7 +522,7 @@ static char *jis8_to_sj(char *from, BOOL overwrite)
}
*out = 0;
if (overwrite) {
- strcpy (save, (char *) cvtbuf);
+ pstrcpy (save, (char *) cvtbuf);
return save;
} else {
return cvtbuf;
@@ -578,7 +578,7 @@ static char *sj_to_jis8(char *from, BOOL overwrite)
}
*out = 0;
if (overwrite) {
- strcpy (save, (char *) cvtbuf);
+ pstrcpy (save, (char *) cvtbuf);
return save;
} else {
return cvtbuf;
@@ -637,7 +637,7 @@ static char *jis7_to_sj(char *from, BOOL overwrite)
}
*out = 0;
if (overwrite) {
- strcpy (save, (char *) cvtbuf);
+ pstrcpy (save, (char *) cvtbuf);
return save;
} else {
return cvtbuf;
@@ -713,7 +713,7 @@ static char *sj_to_jis7(char *from, BOOL overwrite)
}
*out = 0;
if (overwrite) {
- strcpy (save, (char *) cvtbuf);
+ pstrcpy (save, (char *) cvtbuf);
return save;
} else {
return cvtbuf;
@@ -769,7 +769,7 @@ static char *junet_to_sj(char *from, BOOL overwrite)
}
*out = 0;
if (overwrite) {
- strcpy (save, (char *) cvtbuf);
+ pstrcpy (save, (char *) cvtbuf);
return save;
} else {
return cvtbuf;
@@ -838,7 +838,7 @@ static char *sj_to_junet(char *from, BOOL overwrite)
}
*out = 0;
if (overwrite) {
- strcpy (save, (char *) cvtbuf);
+ pstrcpy (save, (char *) cvtbuf);
return save;
} else {
return cvtbuf;
@@ -864,7 +864,7 @@ static char *hex_to_sj(char *from, BOOL overwrite)
}
*dp = '\0';
if (overwrite) {
- strcpy ((char *) from, (char *) cvtbuf);
+ pstrcpy ((char *) from, (char *) cvtbuf);
return (char *) from;
} else {
return cvtbuf;
@@ -900,7 +900,7 @@ static char *sj_to_hex(char *from, BOOL overwrite)
}
*dp = '\0';
if (overwrite) {
- strcpy ((char *) from, (char *) cvtbuf);
+ pstrcpy ((char *) from, (char *) cvtbuf);
return (char *) from;
} else {
return cvtbuf;
@@ -932,7 +932,7 @@ static char *cap_to_sj(char *from, BOOL overwrite)
}
*dp = '\0';
if (overwrite) {
- strcpy ((char *) from, (char *) cvtbuf);
+ pstrcpy ((char *) from, (char *) cvtbuf);
return (char *) from;
} else {
return cvtbuf;
@@ -960,7 +960,7 @@ static char *sj_to_cap(char *from, BOOL overwrite)
}
*dp = '\0';
if (overwrite) {
- strcpy ((char *) from, (char *) cvtbuf);
+ pstrcpy ((char *) from, (char *) cvtbuf);
return (char *) from;
} else {
return cvtbuf;
@@ -973,7 +973,7 @@ static char *sj_to_cap(char *from, BOOL overwrite)
static char *sj_to_sj(char *from, BOOL overwrite)
{
if (!overwrite) {
- strcpy (cvtbuf, (char *) from);
+ pstrcpy (cvtbuf, (char *) from);
return cvtbuf;
} else {
return (char *) from;
diff --git a/source/lib/pidfile.c b/source/lib/pidfile.c
index 46d6a9d5b8c..9cb3f5afef4 100644
--- a/source/lib/pidfile.c
+++ b/source/lib/pidfile.c
@@ -58,7 +58,7 @@ void pidfile_create(char *name)
}
memset(buf, 0, sizeof(buf));
- sprintf(buf, "%u\n", (unsigned int) getpid());
+ slprintf(buf, sizeof(buf) - 1, "%u\n", (unsigned int) getpid());
if (write(fd, buf, sizeof(buf)) != sizeof(buf)) {
DEBUG(0,("ERROR: can't write to %s: %s\n",
pidFile, strerror(errno)));
diff --git a/source/lib/slprintf.c b/source/lib/slprintf.c
index e2dc0e12354..9a00585ca8f 100644
--- a/source/lib/slprintf.c
+++ b/source/lib/slprintf.c
@@ -41,7 +41,15 @@ int vslprintf(char *str, int n, char *format, va_list ap)
/* note: we don't free the old memory (if any) as we don't
want a malloc lib to reuse the memory as it will
have the wrong permissions */
+#ifdef HAVE_MEMALIGN
buf = memalign(pagesize, len);
+#else /* HAVE_MEMALIGN */
+#ifdef HAVE_VALLOC
+ buf = valloc(len);
+#else /* HAVE_VALLOC */
+ buf = malloc(len);
+#endif /* HAVE_VALLOC */
+#endif /* HAVE_MEMALIGN */
if (buf) {
if (mprotect(buf+(len-pagesize), pagesize, PROT_READ) != 0) {
exit(1);
diff --git a/source/lib/time.c b/source/lib/time.c
index 716f5d62cc6..f5c40f0ba08 100644
--- a/source/lib/time.c
+++ b/source/lib/time.c
@@ -486,7 +486,7 @@ char *timestring(void )
int zone = TimeDiff(t);
int absZoneMinutes = (zone<0 ? -zone : zone) / 60;
size_t len = strftime(TimeBuf,sizeof(TimeBuf)-6,"%Y/%m/%d %T",tm);
- sprintf(TimeBuf+len," %c%02d%02d",
+ slprintf(TimeBuf+len, sizeof(fstring) - len - 1, " %c%02d%02d",
zone<0?'+':'-',absZoneMinutes/60,absZoneMinutes%60);
}
#else
diff --git a/source/lib/util.c b/source/lib/util.c
index d2600512e28..f1ea1931c58 100644
--- a/source/lib/util.c
+++ b/source/lib/util.c
@@ -178,14 +178,14 @@ void reopen_logs(void)
if (DEBUGLEVEL > 0)
{
- strcpy(fname,debugf);
+ pstrcpy(fname,debugf);
if (lp_loaded() && (*lp_logfile()))
- strcpy(fname,lp_logfile());
+ pstrcpy(fname,lp_logfile());
if (!strcsequal(fname,debugf) || !dbf || !file_exist(debugf,NULL))
{
int oldumask = umask(022);
- strcpy(debugf,fname);
+ pstrcpy(debugf,fname);
if (dbf) fclose(dbf);
if (append_log)
dbf = fopen(debugf,"a");
@@ -581,7 +581,7 @@ set user socket options
****************************************************************************/
void set_socket_options(int fd, char *options)
{
- string tok;
+ fstring tok;
while (next_token(&options,tok," \t,"))
{
@@ -767,7 +767,7 @@ int name_mangle( char *In, char *Out, char name_type )
if( '*' == In[0] )
buf[0] = '*';
else
- (void)sprintf( buf, "%-15.15s%c", In, name_type );
+ (void)slprintf( buf, sizeof(buf) - 1, "%-15.15s%c", In, name_type );
/* Place the length of the first field into the output buffer. */
p[0] = 32;
@@ -869,16 +869,16 @@ return a string representing an attribute for a file
********************************************************************/
char *attrib_string(int mode)
{
- static char attrstr[10];
+ static fstring attrstr;
attrstr[0] = 0;
- if (mode & aVOLID) strcat(attrstr,"V");
- if (mode & aDIR) strcat(attrstr,"D");
- if (mode & aARCH) strcat(attrstr,"A");
- if (mode & aHIDDEN) strcat(attrstr,"H");
- if (mode & aSYSTEM) strcat(attrstr,"S");
- if (mode & aRONLY) strcat(attrstr,"R");
+ if (mode & aVOLID) fstrcat(attrstr,"V");
+ if (mode & aDIR) fstrcat(attrstr,"D");
+ if (mode & aARCH) fstrcat(attrstr,"A");
+ if (mode & aHIDDEN) fstrcat(attrstr,"H");
+ if (mode & aSYSTEM) fstrcat(attrstr,"S");
+ if (mode & aRONLY) fstrcat(attrstr,"R");
return(attrstr);
}
@@ -1244,8 +1244,8 @@ void unix_format(char *fname)
if (*fname == '/')
{
pstrcpy(namecopy,fname);
- strcpy(fname,".");
- strcat(fname,namecopy);
+ pstrcpy(fname,".");
+ pstrcat(fname,namecopy);
}
}
@@ -1447,7 +1447,7 @@ void dos_clean_name(char *s)
*p = 0;
else
*s = 0;
- strcat(s,s1);
+ pstrcat(s,s1);
}
trim_string(s,NULL,"\\..");
@@ -1471,7 +1471,7 @@ void unix_clean_name(char *s)
if(strncmp(s, "./", 2) == 0) {
trim_string(s, "./", NULL);
if(*s == 0)
- strcpy(s,"./");
+ pstrcpy(s,"./");
}
while ((p = strstr(s,"/../")) != NULL)
@@ -1485,7 +1485,7 @@ void unix_clean_name(char *s)
*p = 0;
else
*s = 0;
- strcat(s,s1);
+ pstrcat(s,s1);
}
trim_string(s,NULL,"/..");
@@ -1578,7 +1578,7 @@ char *GetWd(char *str)
st.st_dev == st2.st_dev &&
(st2.st_mode & S_IFMT) == S_IFDIR)
{
- strcpy (str, ino_list[i].text);
+ pstrcpy (str, ino_list[i].text);
/* promote it for future use */
array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
@@ -1605,7 +1605,7 @@ char *GetWd(char *str)
return (NULL);
}
- strcpy(str,s);
+ pstrcpy(str,s);
DEBUG(5,("GetWd %s, inode %d, dev %x\n",s,(int)st.st_ino,(int)st.st_dev));
@@ -1656,7 +1656,7 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks)
}
if (strlen(s) == 0)
- strcpy(s,"./");
+ pstrcpy(s,"./");
return(True);
}
@@ -1717,8 +1717,8 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks)
if (p && (p != base_name))
{
- strcat(newname,"/");
- strcat(newname,p+1);
+ pstrcat(newname,"/");
+ pstrcat(newname,p+1);
}
{
@@ -1747,7 +1747,7 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks)
ChDir(wd);
if (strlen(s) == 0)
- strcpy(s,"./");
+ pstrcpy(s,"./");
DEBUG(3,("reduced to %s\n",s));
return(True);
@@ -1802,7 +1802,7 @@ void expand_mask(char *Mask,BOOL doext)
}
else
{
- strcpy(mext,"");
+ pstrcpy(mext,"");
if (strlen(mbeg) > 8)
{
pstrcpy(mext,mbeg + 8);
@@ -1811,12 +1811,12 @@ void expand_mask(char *Mask,BOOL doext)
}
if (*mbeg == 0)
- strcpy(mbeg,"????????");
+ pstrcpy(mbeg,"????????");
if ((*mext == 0) && doext && !hasdot)
- strcpy(mext,"???");
+ pstrcpy(mext,"???");
if (strequal(mbeg,"*") && *mext==0)
- strcpy(mext,"*");
+ pstrcpy(mext,"*");
/* expand *'s */
expand_one(mbeg,8);
@@ -1824,10 +1824,10 @@ void expand_mask(char *Mask,BOOL doext)
expand_one(mext,3);
pstrcpy(Mask,dirpart);
- if (*dirpart || absolute) strcat(Mask,"\\");
- strcat(Mask,mbeg);
- strcat(Mask,".");
- strcat(Mask,mext);
+ if (*dirpart || absolute) pstrcat(Mask,"\\");
+ pstrcat(Mask,mbeg);
+ pstrcat(Mask,".");
+ pstrcat(Mask,mext);
DEBUG(6,("Mask expanded to [%s]\n",Mask));
}
@@ -2769,7 +2769,7 @@ int name_extract(char *buf,int ofs,char *name)
{
char *p = name_ptr(buf,ofs);
int d = PTR_DIFF(p,buf+ofs);
- strcpy(name,"");
+ pstrcpy(name,"");
if (d < -50 || d > 50) return(0);
return(name_interpret(p,name));
}
@@ -2913,7 +2913,7 @@ BOOL string_init(char **dest,char *src)
return False;
}
- strcpy(*dest,src);
+ pstrcpy(*dest,src);
}
return(True);
}
@@ -3057,12 +3057,12 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
StrnCpy(p2,str,sizeof(pstring)-1);
if (!strchr(p2,'.')) {
- strcat(p2,".");
+ pstrcat(p2,".");
}
/*
if (!strchr(p1,'.')) {
- strcat(p1,".");
+ pstrcat(p1,".");
}
*/
@@ -3077,7 +3077,7 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
/* Remove any *? and ** as they are meaningless */
for(p = p1; *p; p++)
while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
- (void)strcpy( &p[1], &p[2]);
+ (void)pstrcpy( &p[1], &p[2]);
if (strequal(p1,"*")) return(True);
@@ -3310,11 +3310,11 @@ char *dirname_dos(char *path,char *buf)
char *p = strrchr(path,'\\');
if (!p)
- strcpy(buf,path);
+ pstrcpy(buf,path);
else
{
*p = 0;
- strcpy(buf,path);
+ pstrcpy(buf,path);
*p = '\\';
}
@@ -3330,9 +3330,9 @@ static char *filename_dos(char *path,char *buf)
char *p = strrchr(path,'\\');
if (!p)
- strcpy(buf,path);
+ pstrcpy(buf,path);
else
- strcpy(buf,p+1);
+ pstrcpy(buf,p+1);
return(buf);
}
@@ -3373,7 +3373,7 @@ duplicate a string
if (!s) return(NULL);
ret = (char *)malloc(strlen(s)+1);
if (!ret) return(NULL);
- strcpy(ret,s);
+ pstrcpy(ret,s);
return(ret);
}
#endif
@@ -3748,7 +3748,7 @@ char *client_name(int fd)
last_fd = fd;
global_client_name_done = False;
- strcpy(name_buf,"UNKNOWN");
+ pstrcpy(name_buf,"UNKNOWN");
if (fd == -1) {
return name_buf;
@@ -3769,7 +3769,7 @@ char *client_name(int fd)
StrnCpy(name_buf,(char *)hp->h_name,sizeof(name_buf) - 1);
if (!matchname(name_buf, sockin->sin_addr)) {
DEBUG(0,("Matchname failed on %s %s\n",name_buf,client_addr(fd)));
- strcpy(name_buf,"UNKNOWN");
+ pstrcpy(name_buf,"UNKNOWN");
}
}
global_client_name_done = True;
@@ -3793,7 +3793,7 @@ char *client_addr(int fd)
last_fd = fd;
global_client_addr_done = False;
- strcpy(addr_buf,"0.0.0.0");
+ fstrcpy(addr_buf,"0.0.0.0");
if (fd == -1) {
return addr_buf;
@@ -3980,7 +3980,7 @@ char *automount_path(char *user_name)
{
DEBUG(5, ("NIS lookup succeeded. Home path is: %s\n",
home_path_start?(home_path_start+1):""));
- strcpy(server_path, home_path_start+1);
+ pstrcpy(server_path, home_path_start+1);
}
}
#endif
@@ -4029,7 +4029,7 @@ void standard_sub_basic(char *str)
case 'a' : string_sub(p,"%a", remote_arch); break;
case 'd' :
{
- sprintf(pidstr,"%d",(int)getpid());
+ slprintf(pidstr,sizeof(pidstr) - 1, "%d",(int)getpid());
string_sub(p,"%d", pidstr);
break;
}
@@ -4184,7 +4184,7 @@ char *uidtoname(int uid)
static char name[40];
struct passwd *pass = getpwuid(uid);
if (pass) return(pass->pw_name);
- sprintf(name,"%d",uid);
+ slprintf(name, sizeof(name) - 1, "%d",uid);
return(name);
}
@@ -4196,7 +4196,7 @@ char *gidtoname(int gid)
static char name[40];
struct group *grp = getgrgid(gid);
if (grp) return(grp->gr_name);
- sprintf(name,"%d",gid);
+ slprintf(name,sizeof(name) - 1, "%d",gid);
return(name);
}
@@ -4600,23 +4600,23 @@ void set_remote_arch(enum remote_arch_types type)
switch( type )
{
case RA_WFWG:
- strcpy(remote_arch, "WfWg");
+ fstrcpy(remote_arch, "WfWg");
return;
case RA_OS2:
- strcpy(remote_arch, "OS2");
+ fstrcpy(remote_arch, "OS2");
return;
case RA_WIN95:
- strcpy(remote_arch, "Win95");
+ fstrcpy(remote_arch, "Win95");
return;
case RA_WINNT:
- strcpy(remote_arch, "WinNT");
+ fstrcpy(remote_arch, "WinNT");
return;
case RA_SAMBA:
- strcpy(remote_arch,"Samba");
+ fstrcpy(remote_arch,"Samba");
return;
default:
ra_type = RA_UNKNOWN;
- strcpy(remote_arch, "UNKNOWN");
+ fstrcpy(remote_arch, "UNKNOWN");
break;
}
}
@@ -4793,7 +4793,7 @@ int unistrcpy(char *dst, char *src)
return num_wchars;
}
-
+#if 0
/*******************************************************************
safe string copy into a fstring
********************************************************************/
@@ -4824,34 +4824,94 @@ void fstrcpy(char *dest, char *src)
}
/*******************************************************************
-safe string copy into a pstring
+safe string cat into a fstring
********************************************************************/
-void pstrcpy(char *dest, char *src)
+void fstrcat(char *dest, char *src)
{
- int maxlength = sizeof(pstring) - 1;
- int len;
+ int maxlength = sizeof(fstring) - 1;
+ int src_len, dest_len;
if (!dest) {
- DEBUG(0,("ERROR: NULL dest in pstrcpy\n"));
+ DEBUG(0,("ERROR: NULL dest in fstrcat\n"));
return;
}
if (!src) {
- *dest = 0;
return;
}
+ src_len = strlen(src);
+ dest_len = strlen(dest);
+
+ if (src_len + dest_len > maxlength) {
+ DEBUG(0,("ERROR: string overflow by %d in fstrcat [%.50s]\n",
+ src_len + dest_len - maxlength, src));
+ src_len = maxlength - dest_len;
+ }
+
+ memcpy(&dest[dest_len], src, src_len);
+ dest[dest_len + src_len] = 0;
+}
+#endif
+
+/*******************************************************************
+safe string copy into a known length string
+********************************************************************/
+char *safe_strcpy(char *dest, char *src, int maxlength)
+{
+ int len;
+
+ if (!dest) {
+ DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
+ return NULL;
+ }
+
+ if (!src) {
+ *dest = 0;
+ return dest;
+ }
+
len = strlen(src);
if (len > maxlength) {
- DEBUG(0,("ERROR: string overflow by %d in pstrcpy [%.50s]\n",
+ DEBUG(0,("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
len-maxlength, src));
len = maxlength;
}
memcpy(dest, src, len);
dest[len] = 0;
+ return dest;
}
+/*******************************************************************
+safe string cat into a string
+********************************************************************/
+char *safe_strcat(char *dest, char *src, int maxlength)
+{
+ int src_len, dest_len;
+
+ if (!dest) {
+ DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
+ return NULL;
+ }
+
+ if (!src) {
+ return dest;
+ }
+
+ src_len = strlen(src);
+ dest_len = strlen(dest);
+
+ if (src_len + dest_len > maxlength) {
+ DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
+ src_len + dest_len - maxlength, src));
+ src_len = maxlength - dest_len;
+ }
+
+ memcpy(&dest[dest_len], src, src_len);
+ dest[dest_len + src_len] = 0;
+ return dest;
+}
/*******************************************************************
align a pointer to a multiple of 4 bytes
@@ -4954,12 +5014,12 @@ char *dom_sid_to_string(DOM_SID *sid)
(sid->id_auth[3] << 16) +
(sid->id_auth[2] << 24);
- sprintf(sidstr, "S-%d-%d", sid->sid_rev_num, ia);
+ slprintf(sidstr, sizeof(sidstr) - 1, "S-%d-%d", sid->sid_rev_num, ia);
for (i = 0; i < sid->num_auths; i++)
{
- sprintf(subauth, "-%d", sid->sub_auths[i]);
- strcat(sidstr, subauth);
+ slprintf(subauth, sizeof(subauth)-1, "-%d", sid->sub_auths[i]);
+ pstrcat(sidstr, subauth);
}
DEBUG(7,("dom_sid_to_string returning %s\n", sidstr));