From e88ec187cdd590f7b9155cef3ee276c268a4a522 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 25 Jan 2016 17:04:48 +0000 Subject: [PATCH 1/5] Fix issues on unix with opening database files via symlinks that are not in the current working directory. And with nested symlinks. FossilOrigin-Name: 80398fd44fb232193450103808e1854e0eba5652 --- manifest | 19 +++--- manifest.uuid | 2 +- src/os_unix.c | 154 +++++++++++++++++++++++++++++++++------------- test/symlink.test | 119 ++++++++++++++++++++++++++--------- 4 files changed, 215 insertions(+), 79 deletions(-) diff --git a/manifest b/manifest index 827a3d5126..0b395a1661 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Replace\sthe\sOP_SetIfNotPos\soperator\swith\sOP_OffsetLimit\sin\sthe\sVDBE,\sfor\nsimpler\sand\ssmaller\scode. -D 2016-01-25T15:57:29.060 +C Fix\sissues\son\sunix\swith\sopening\sdatabase\sfiles\svia\ssymlinks\sthat\sare\snot\sin\sthe\scurrent\sworking\sdirectory.\sAnd\swith\snested\ssymlinks. +D 2016-01-25T17:04:48.546 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -329,7 +329,7 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c 0eb7f469fcd4e1fbedf30060438e26b839ec5486 +F src/os_unix.c cf524029242b4f878d6b97bad25cc2c0b66c2b31 F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 2916c66aee50f69d9ec56a7619b62d9c6a3bee61 @@ -1061,7 +1061,7 @@ F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4 F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8 F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2 -F test/symlink.test cbf6cb8c6c4b63a39e9f0f6b0d5c99e249dbc102 +F test/symlink.test 511db82662446bb0d3619002422760ef8e4b1122 F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85 F test/syscall.test 2aa9e111b79fb385681ff8940124def6f8faab87 F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04 @@ -1419,7 +1419,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 30671345b1c1ee55a2d1aa17273213f1849efd81 -R f342889ba3409bd63b1cf54d88bfe0e2 -U drh -Z e7c5fc86067d4269675714897cec0b51 +P 7ac017a498b6fb28343eef2d24e400c7800660d6 +R 0289127606d03bb3b649ecbd39bb14a5 +T *branch * follow-symlinks +T *sym-follow-symlinks * +T -sym-trunk * +U dan +Z 3e18b3d01ba737d3635110839e378935 diff --git a/manifest.uuid b/manifest.uuid index 276ef7a03f..6dda1af216 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7ac017a498b6fb28343eef2d24e400c7800660d6 \ No newline at end of file +80398fd44fb232193450103808e1854e0eba5652 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index ee9b55674b..9cd1fa19ad 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -149,6 +149,11 @@ */ #define MAX_PATHNAME 512 +/* +** Maximum supported symbolic links +*/ +#define SQLITE_MAX_SYMLINKS 100 + /* Always cast the getpid() return type for compatibility with ** kernel modules in VxWorks. */ #define osGetpid(X) (pid_t)getpid() @@ -5927,52 +5932,22 @@ static int unixAccess( return SQLITE_OK; } - /* -** Turn a relative pathname into a full pathname. The relative path -** is stored as a nul-terminated string in the buffer pointed to by -** zPath. +** Buffer zOut contains a (possibly) relative pathname. Overwrite it with +** the corresponding full pathname. ** -** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes -** (in this case, MAX_PATHNAME bytes). The full-path is written to -** this buffer before returning. +** Parameter nOut is the allocated size of buffer zOut. nByte is the number +** of bytes in the nul-terminated string that it contains (not including +** the nul-terminator itself). +** +** Return SQLITE_OK if successful, or an SQLite error code otherwise. */ -static int unixFullPathname( - sqlite3_vfs *pVfs, /* Pointer to vfs object */ - const char *zPath, /* Possibly relative input path */ - int nOut, /* Size of output buffer in bytes */ - char *zOut /* Output buffer */ +static int mkFullPathname( + const char *zPath, /* Use this path to log any errors */ + char *zOut, /* IN/OUT: Buffer to modify */ + int nByte, /* size of nul-terminated zOut in bytes */ + int nOut /* Allocated size of buffer zOut */ ){ - int nByte; - - /* It's odd to simulate an io-error here, but really this is just - ** using the io-error infrastructure to test that SQLite handles this - ** function failing. This function could fail if, for example, the - ** current working directory has been unlinked. - */ - SimulateIOError( return SQLITE_ERROR ); - - assert( pVfs->mxPathname==MAX_PATHNAME ); - UNUSED_PARAMETER(pVfs); - -#if defined(HAVE_READLINK) - /* Attempt to resolve the path as if it were a symbolic link. If it is - ** a symbolic link, the resolved path is stored in buffer zOut[]. Or, if - ** the identified file is not a symbolic link or does not exist, then - ** zPath is copied directly into zOut. Either way, nByte is left set to - ** the size of the string copied into zOut[] in bytes. */ - nByte = osReadlink(zPath, zOut, nOut-1); - if( nByte<0 ){ - if( errno!=EINVAL && errno!=ENOENT ){ - return unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zPath); - } - sqlite3_snprintf(nOut, zOut, "%s", zPath); - nByte = sqlite3Strlen30(zOut); - }else{ - zOut[nByte] = '\0'; - } -#endif - /* If buffer zOut[] now contains an absolute path there is nothing more ** to do. If it contains a relative path, do the following: ** @@ -5989,6 +5964,7 @@ static int unixFullPathname( ** truncated to make it fit. This is Ok, as SQLite refuses to open any ** file for which this function returns a full path larger than (nOut-8) ** bytes in size. */ + assert( nBytemxPathname==MAX_PATHNAME ); + UNUSED_PARAMETER(pVfs); + + /* It's odd to simulate an io-error here, but really this is just + ** using the io-error infrastructure to test that SQLite handles this + ** function failing. This function could fail if, for example, the + ** current working directory has been unlinked. + */ + SimulateIOError( return SQLITE_ERROR ); + + do { + + /* Attempt to resolve the path as if it were a symbolic link. If it is + ** a symbolic link, the resolved path is stored in buffer zOut[]. Or, if + ** the identified file is not a symbolic link or does not exist, then + ** zPath is copied directly into zOut. Either way, nByte is left set to + ** the size of the string copied into zOut[] in bytes. */ + assert( (zDel==0 && zIn==zPath) || (zDel!=0 && zIn==zDel) ); + if( zDel ){ + assert( zIn==zDel ); + sqlite3_snprintf(nOut, zDel, "%s", zOut); + } + nByte = osReadlink(zIn, zOut, nOut-1); + if( nByte<0 ){ + if( errno!=EINVAL && errno!=ENOENT ){ + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zPath); + }else{ + sqlite3_snprintf(nOut, zOut, "%s", zIn); + nByte = sqlite3Strlen30(zOut); + } + bLink = 0; + }else if( ++nLink>SQLITE_MAX_SYMLINKS ){ + sqlite3_log(SQLITE_CANTOPEN, + "too many symbolic links (max=%d)", SQLITE_MAX_SYMLINKS + ); + rc = SQLITE_CANTOPEN_BKPT; + }else{ + zOut[nByte] = '\0'; + if( zOut[0]!='/' ){ + int n; + for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--); + if( nByte+n+1>nOut ){ + rc = SQLITE_CANTOPEN_BKPT; + }else{ + memmove(&zOut[n], zOut, nByte+1); + memcpy(zOut, zIn, n); + nByte += n; + } + } + if( zDel==0 ){ + zDel = sqlite3_malloc(nOut); + if( zDel==0 ) rc = SQLITE_NOMEM; + zIn = (const char*)zDel; + } + bLink = 1; + } + + if( rc==SQLITE_OK ){ + rc = mkFullPathname(zPath, zOut, nByte, nOut); + } + }while( bLink && rc==SQLITE_OK ); + + sqlite3_free(zDel); + return rc; +#endif /* HAVE_READLINK */ +} + #ifndef SQLITE_OMIT_LOAD_EXTENSION /* diff --git a/test/symlink.test b/test/symlink.test index 790624161f..e9e5f3c305 100644 --- a/test/symlink.test +++ b/test/symlink.test @@ -83,38 +83,49 @@ do_test 1.5 { do_test 2.0 { catch { db close } catch { db2 close } - forcedelete test.db test.db2 + forcedelete test.db test.db2 test.db3 sqlite3 db test.db execsql { CREATE TABLE t1(x) } file link test.db2 test.db - sqlite3 db2 test.db2 - file exists test.db-journal -} 0 + file link test.db3 test.db2 + set {} {} +} {} -do_test 2.1 { - execsql { - BEGIN; - INSERT INTO t1 VALUES(1); - } db2 - file exists test.db-journal -} 1 -do_test 2.2 { - file exists test.db2-journal -} 0 -do_test 2.3 { - execsql { - COMMIT; - PRAGMA journal_mode = wal; - INSERT INTO t1 VALUES(2); - } db2 - file exists test.db-wal -} 1 -do_test 2.4 { - file exists test.db2-wal -} 0 -do_execsql_test 2.5 { - SELECT * FROM t1; -} {1 2} +foreach {tn f} {1 test.db2 2 test.db3} { + do_test 2.$tn.1 { + sqlite3 db2 $f + file exists test.db-journal + } 0 + do_test 2.$tn.2 { + execsql { + BEGIN; + INSERT INTO t1 VALUES(1); + } db2 + file exists test.db-journal + } 1 + do_test 2.$tn.3 { + list [file exists test2.db-journal] [file exists test3.db-journal] + } {0 0} + do_test 2.$tn.4 { + execsql { + COMMIT; + PRAGMA journal_mode = wal; + INSERT INTO t1 VALUES(2); + } db2 + file exists test.db-wal + } 1 + do_test 2.$tn.5 { + list [file exists test2.db-wal] [file exists test3.db-wal] + } {0 0} + do_execsql_test 2.$tn.6 { + SELECT * FROM t1; + } {1 2} + db2 close + do_execsql_test 2.$tn.7 { + DELETE FROM t1; + PRAGMA journal_mode = delete; + } delete +} # Try to open a ridiculously long pathname. Bug found by # Kostya Serebryany using libFuzzer on 2015-11-30. @@ -125,5 +136,57 @@ do_test 3.1 { set res } {unable to open database file} +#------------------------------------------------------------------------- +# Test that relative symlinks that are not located in the cwd work. +# +do_test 4.1 { + forcedelete x y z + file mkdir x + file mkdir y + file mkdir z + sqlite3 db x/test.db + file link y/test.db ../x/test.db + file link z/test.db ../y/test.db + execsql { + PRAGMA journal_mode = wal; + CREATE TABLE t1(x, y); + INSERT INTO t1 VALUES('hello', 'world'); + } +} {wal} + +do_test 4.2.1 { + db close + sqlite3 db y/test.db + db eval { SELECT * FROM t1 } +} {hello world} +do_test 4.2.2 { + list [file exists x/test.db-wal] [file exists y/test.db-wal] +} {1 0} + +do_test 4.3.1 { + db close + sqlite3 db z/test.db + db eval { SELECT * FROM t1 } +} {hello world} +do_test 4.3.2 { + list [file exists x/test.db-wal] [file exists y/test.db-wal] \ + [file exists z/test.db-wal] +} {1 0 0} + +do_test 4.4.0 { + forcedelete w + file mkdir w + file link w/test.db [file join [pwd] x/test.db] + set {} {} +} {} +do_test 4.4.1 { + db close + breakpoint + sqlite3 db w/test.db + db eval { SELECT * FROM t1 } +} {hello world} +do_test 4.4.2 { + list [file exists x/test.db-wal] [file exists w/test.db-wal] +} {1 0} finish_test From caf6b150a1077f2d4293b4091247c7e932da3927 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 25 Jan 2016 18:05:49 +0000 Subject: [PATCH 2/5] Simplify the unixFullpathname() function. This adds a dependency on lstat(). FossilOrigin-Name: f71249d3db9242b8f38955db51a7a5789d002803 --- manifest | 15 +++--- manifest.uuid | 2 +- src/os_unix.c | 137 +++++++++++++++++++------------------------------- 3 files changed, 60 insertions(+), 94 deletions(-) diff --git a/manifest b/manifest index 0b395a1661..27188d419f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sissues\son\sunix\swith\sopening\sdatabase\sfiles\svia\ssymlinks\sthat\sare\snot\sin\sthe\scurrent\sworking\sdirectory.\sAnd\swith\snested\ssymlinks. -D 2016-01-25T17:04:48.546 +C Simplify\sthe\sunixFullpathname()\sfunction.\sThis\sadds\sa\sdependency\son\slstat(). +D 2016-01-25T18:05:49.964 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -329,7 +329,7 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c cf524029242b4f878d6b97bad25cc2c0b66c2b31 +F src/os_unix.c 6604e7f9e5298b615f729b6bb3c22bd3545cdca6 F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 2916c66aee50f69d9ec56a7619b62d9c6a3bee61 @@ -1419,10 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 7ac017a498b6fb28343eef2d24e400c7800660d6 -R 0289127606d03bb3b649ecbd39bb14a5 -T *branch * follow-symlinks -T *sym-follow-symlinks * -T -sym-trunk * +P 80398fd44fb232193450103808e1854e0eba5652 +R 084dee05e1353887f6af0d88670b22d0 U dan -Z 3e18b3d01ba737d3635110839e378935 +Z 72572e009a3ce3b7747f3257ebf7dfc7 diff --git a/manifest.uuid b/manifest.uuid index 6dda1af216..b66c39a6ae 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -80398fd44fb232193450103808e1854e0eba5652 \ No newline at end of file +f71249d3db9242b8f38955db51a7a5789d002803 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 9cd1fa19ad..3d113301b8 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -480,6 +480,8 @@ static struct unix_syscall { #endif #define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent) + { "lstat", (sqlite3_syscall_ptr)lstat, 0 }, +#define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent) }; /* End of the overrideable system calls */ @@ -5933,54 +5935,24 @@ static int unixAccess( } /* -** Buffer zOut contains a (possibly) relative pathname. Overwrite it with -** the corresponding full pathname. ** -** Parameter nOut is the allocated size of buffer zOut. nByte is the number -** of bytes in the nul-terminated string that it contains (not including -** the nul-terminator itself). -** -** Return SQLITE_OK if successful, or an SQLite error code otherwise. */ static int mkFullPathname( - const char *zPath, /* Use this path to log any errors */ - char *zOut, /* IN/OUT: Buffer to modify */ - int nByte, /* size of nul-terminated zOut in bytes */ + const char *zPath, /* Input path */ + char *zOut, /* Output buffer */ int nOut /* Allocated size of buffer zOut */ ){ - /* If buffer zOut[] now contains an absolute path there is nothing more - ** to do. If it contains a relative path, do the following: - ** - ** * move the relative path string so that it is at the end of th - ** zOut[] buffer. - ** * Call getcwd() to read the path of the current working directory - ** into the start of the zOut[] buffer. - ** * Append a '/' character to the cwd string and move the - ** relative path back within the buffer so that it immediately - ** follows the '/'. - ** - ** This code is written so that if the combination of the CWD and relative - ** path are larger than the allocated size of zOut[] the CWD is silently - ** truncated to make it fit. This is Ok, as SQLite refuses to open any - ** file for which this function returns a full path larger than (nOut-8) - ** bytes in size. */ - assert( nBytenOut ) return SQLITE_CANTOPEN_BKPT; + sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath); return SQLITE_OK; } @@ -6000,13 +5972,11 @@ static int unixFullPathname( char *zOut /* Output buffer */ ){ #if !defined(HAVE_READLINK) - sqlite3_snprintf(nOut, zOut, "%s", zIn); - nByte = sqlite3Strlen30(zOut); - return mkFullPathname(zPath, zOut, sqlite3Strlen30(zOut), nOut); + return mkFullPathname(zPath, zOut, nOut); #else int rc = SQLITE_OK; int nByte; - int nLink = 0; /* Number of symbolic links followed so far */ + int nLink = 1; /* Number of symbolic links followed so far */ int bLink; /* True for a symbolic link */ const char *zIn = zPath; /* Input path for each iteration of loop */ char *zDel = 0; @@ -6023,55 +5993,54 @@ static int unixFullPathname( do { - /* Attempt to resolve the path as if it were a symbolic link. If it is - ** a symbolic link, the resolved path is stored in buffer zOut[]. Or, if - ** the identified file is not a symbolic link or does not exist, then - ** zPath is copied directly into zOut. Either way, nByte is left set to - ** the size of the string copied into zOut[] in bytes. */ - assert( (zDel==0 && zIn==zPath) || (zDel!=0 && zIn==zDel) ); - if( zDel ){ - assert( zIn==zDel ); - sqlite3_snprintf(nOut, zDel, "%s", zOut); - } - nByte = osReadlink(zIn, zOut, nOut-1); - if( nByte<0 ){ - if( errno!=EINVAL && errno!=ENOENT ){ - rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zPath); - }else{ - sqlite3_snprintf(nOut, zOut, "%s", zIn); - nByte = sqlite3Strlen30(zOut); + /* Call stat() on path zIn. Set bLink to true if the path is a symbolic + ** link, or false otherwise. */ + int bLink = 0; + struct stat buf; + if( osLstat(zIn, &buf)!=0 ){ + if( errno!=ENOENT ){ + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "stat", zIn); } - bLink = 0; - }else if( ++nLink>SQLITE_MAX_SYMLINKS ){ - sqlite3_log(SQLITE_CANTOPEN, - "too many symbolic links (max=%d)", SQLITE_MAX_SYMLINKS - ); - rc = SQLITE_CANTOPEN_BKPT; }else{ - zOut[nByte] = '\0'; - if( zOut[0]!='/' ){ - int n; - for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--); - if( nByte+n+1>nOut ){ - rc = SQLITE_CANTOPEN_BKPT; - }else{ - memmove(&zOut[n], zOut, nByte+1); - memcpy(zOut, zIn, n); - nByte += n; - } - } + bLink = S_ISLNK(buf.st_mode); + } + + if( bLink ){ if( zDel==0 ){ zDel = sqlite3_malloc(nOut); if( zDel==0 ) rc = SQLITE_NOMEM; - zIn = (const char*)zDel; + }else if( ++nLink>SQLITE_MAX_SYMLINKS ){ + rc = SQLITE_CANTOPEN_BKPT; } - bLink = 1; + + if( rc==SQLITE_OK ){ + nByte = osReadlink(zIn, zDel, nOut-1); + if( nByte<0 ){ + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn); + }else if( zDel[0]!='/' ){ + int n; + for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--); + if( nByte+n+1>nOut ){ + rc = SQLITE_CANTOPEN_BKPT; + }else{ + memmove(&zDel[n], zDel, nByte+1); + memcpy(zDel, zIn, n); + nByte += n; + } + zDel[nByte] = '\0'; + } + } + + zIn = zDel; } if( rc==SQLITE_OK ){ - rc = mkFullPathname(zPath, zOut, nByte, nOut); + assert( zIn!=zOut || zIn[0]=='/' ); + rc = mkFullPathname(zIn, zOut, nOut); } - }while( bLink && rc==SQLITE_OK ); + if( bLink==0 ) break; + zIn = zOut; + }while( rc==SQLITE_OK ); sqlite3_free(zDel); return rc; @@ -7574,7 +7543,7 @@ int sqlite3_os_init(void){ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ - assert( ArraySize(aSyscall)==27 ); + assert( ArraySize(aSyscall)==28 ); /* Register all VFSes defined in the aVfs[] array */ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ From af1b36b1df592aa8ecf1fd8799db7e415688ed6e Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 25 Jan 2016 18:43:05 +0000 Subject: [PATCH 3/5] Only use lstat() if the HAVE_LSTAT macro is defined. Fix some test file issues. FossilOrigin-Name: 8a6e4147a680ad6c5fdd588468b6daac82349d2c --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/os_unix.c | 12 ++++++++---- src/vxworks.h | 1 + test/oserror.test | 2 +- test/syscall.test | 2 +- 6 files changed, 21 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index 27188d419f..33b8dc8b5c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simplify\sthe\sunixFullpathname()\sfunction.\sThis\sadds\sa\sdependency\son\slstat(). -D 2016-01-25T18:05:49.964 +C Only\suse\slstat()\sif\sthe\sHAVE_LSTAT\smacro\sis\sdefined.\sFix\ssome\stest\sfile\sissues. +D 2016-01-25T18:43:05.007 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -329,7 +329,7 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c 6604e7f9e5298b615f729b6bb3c22bd3545cdca6 +F src/os_unix.c 4c217111d7bdebbd7a9b47cf11f434420da432e7 F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 2916c66aee50f69d9ec56a7619b62d9c6a3bee61 @@ -420,7 +420,7 @@ F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0 F src/vdbesort.c 0971557e5d3c289e46f56a52aed2197c13251de7 F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0 F src/vtab.c 320682cca733115b4cbe71320b5c5eeb1074ebde -F src/vxworks.h 974e7d9a98f602d6310d563e1dc4e08f9fc48e47 +F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c d21b99fd1458159d0b1ecdccc8ee6ada4fdc4c54 F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 @@ -924,7 +924,7 @@ F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859 F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3 -F test/oserror.test 361346396ae18462c7393c1ac5c3f17237bd89b2 +F test/oserror.test b32dc34f2363ef18532e3a0a7358e3e7e321974f F test/ovfl.test 4f7ca651cba5c059a12d8c67dddd49bec5747799 F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71 @@ -1063,7 +1063,7 @@ F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8 F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2 F test/symlink.test 511db82662446bb0d3619002422760ef8e4b1122 F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85 -F test/syscall.test 2aa9e111b79fb385681ff8940124def6f8faab87 +F test/syscall.test f59ba4e25f7ba4a4c031026cc2ef8b6e4b4c639c F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04 F test/tabfunc01.test cc33684f9480fcf1fd5ce287ac28d22971cad1cc F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f @@ -1419,7 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 80398fd44fb232193450103808e1854e0eba5652 -R 084dee05e1353887f6af0d88670b22d0 +P f71249d3db9242b8f38955db51a7a5789d002803 +R 31817b68212f6684c4e9fbfebdae658d U dan -Z 72572e009a3ce3b7747f3257ebf7dfc7 +Z 17d90a7cade21886dca3e4bdfc08ed4c diff --git a/manifest.uuid b/manifest.uuid index b66c39a6ae..35202dd686 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f71249d3db9242b8f38955db51a7a5789d002803 \ No newline at end of file +8a6e4147a680ad6c5fdd588468b6daac82349d2c \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 3d113301b8..a3bb45bdb9 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -480,7 +480,11 @@ static struct unix_syscall { #endif #define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent) - { "lstat", (sqlite3_syscall_ptr)lstat, 0 }, +#if defined(HAVE_LSTAT) + { "lstat", (sqlite3_syscall_ptr)lstat, 0 }, +#else + { "lstat", (sqlite3_syscall_ptr)0, 0 }, +#endif #define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent) }; /* End of the overrideable system calls */ @@ -5971,7 +5975,7 @@ static int unixFullPathname( int nOut, /* Size of output buffer in bytes */ char *zOut /* Output buffer */ ){ -#if !defined(HAVE_READLINK) +#if !defined(HAVE_READLINK) || !defined(HAVE_LSTAT) return mkFullPathname(zPath, zOut, nOut); #else int rc = SQLITE_OK; @@ -5999,7 +6003,7 @@ static int unixFullPathname( struct stat buf; if( osLstat(zIn, &buf)!=0 ){ if( errno!=ENOENT ){ - rc = unixLogError(SQLITE_CANTOPEN_BKPT, "stat", zIn); + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn); } }else{ bLink = S_ISLNK(buf.st_mode); @@ -6044,7 +6048,7 @@ static int unixFullPathname( sqlite3_free(zDel); return rc; -#endif /* HAVE_READLINK */ +#endif /* HAVE_READLINK && HAVE_LSTAT */ } diff --git a/src/vxworks.h b/src/vxworks.h index 60c41a19b8..e7013c3f66 100644 --- a/src/vxworks.h +++ b/src/vxworks.h @@ -28,4 +28,5 @@ #define OS_VXWORKS 0 #define HAVE_FCHOWN 1 #define HAVE_READLINK 1 +#define HAVE_LSTAT 1 #endif /* defined(_WRS_KERNEL) */ diff --git a/test/oserror.test b/test/oserror.test index 5fa7f98eb5..246a9d4023 100644 --- a/test/oserror.test +++ b/test/oserror.test @@ -95,7 +95,7 @@ do_test 1.4.1 { do_re_test 1.4.2 { lindex $::log 0 -} {^os_unix.c:\d*: \(\d+\) (open|readlink)\(.*test.db\) - } +} {^os_unix.c:\d*: \(\d+\) (open|readlink|lstat)\(.*test.db\) - } #-------------------------------------------------------------------------- # Tests oserror-1.* test failures in the unlink() system call. diff --git a/test/syscall.test b/test/syscall.test index a935957d39..5716b35a6e 100644 --- a/test/syscall.test +++ b/test/syscall.test @@ -61,7 +61,7 @@ foreach s { fcntl read pread write pwrite fchmod fallocate pread64 pwrite64 unlink openDirectory mkdir rmdir statvfs fchown geteuid umask mmap munmap mremap - getpagesize readlink + getpagesize readlink lstat } { if {[test_syscall exists $s]} {lappend syscall_list $s} } From f0fc9929369cda0c7416174d43a299188b8beabf Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 26 Jan 2016 00:12:42 +0000 Subject: [PATCH 4/5] Remove an unused variable. FossilOrigin-Name: 1c2656c1d37906230edc142d3a4253b16b6e925f --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/os_unix.c | 1 - 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 33b8dc8b5c..ea40dd333f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Only\suse\slstat()\sif\sthe\sHAVE_LSTAT\smacro\sis\sdefined.\sFix\ssome\stest\sfile\sissues. -D 2016-01-25T18:43:05.007 +C Remove\san\sunused\svariable. +D 2016-01-26T00:12:42.634 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -329,7 +329,7 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c 4c217111d7bdebbd7a9b47cf11f434420da432e7 +F src/os_unix.c e9e1e6a49892a76fe1fd167b1d475eeddaf1ccb3 F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 2916c66aee50f69d9ec56a7619b62d9c6a3bee61 @@ -1419,7 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f71249d3db9242b8f38955db51a7a5789d002803 -R 31817b68212f6684c4e9fbfebdae658d -U dan -Z 17d90a7cade21886dca3e4bdfc08ed4c +P 8a6e4147a680ad6c5fdd588468b6daac82349d2c +R d2cf53f7b50c768b631d5f18bba143b9 +U drh +Z 592370e14c792642f017f87ac074cb77 diff --git a/manifest.uuid b/manifest.uuid index 35202dd686..78b51cd18f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8a6e4147a680ad6c5fdd588468b6daac82349d2c \ No newline at end of file +1c2656c1d37906230edc142d3a4253b16b6e925f \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index a3bb45bdb9..cdbcd2c8e0 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -5981,7 +5981,6 @@ static int unixFullPathname( int rc = SQLITE_OK; int nByte; int nLink = 1; /* Number of symbolic links followed so far */ - int bLink; /* True for a symbolic link */ const char *zIn = zPath; /* Input path for each iteration of loop */ char *zDel = 0; From 23496702622549d23f22639b7e2f5c47cfeba9a6 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 26 Jan 2016 13:56:42 +0000 Subject: [PATCH 5/5] Ensure that unixFullpathname() always nul-terminates its output buffer, even when returning an error. FossilOrigin-Name: 4a4385564dd3887a7953820b60c99d6ce289f96a --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/os_unix.c | 31 +++++++++++++++++++------------ test/symlink.test | 1 - 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/manifest b/manifest index ea40dd333f..2765e104fb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sunused\svariable. -D 2016-01-26T00:12:42.634 +C Ensure\sthat\sunixFullpathname()\salways\snul-terminates\sits\soutput\sbuffer,\seven\swhen\sreturning\san\serror. +D 2016-01-26T13:56:42.494 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9 @@ -329,7 +329,7 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c e9e1e6a49892a76fe1fd167b1d475eeddaf1ccb3 +F src/os_unix.c 5bb20172d0c9a6afcfa829a88c406970593c848d F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 2916c66aee50f69d9ec56a7619b62d9c6a3bee61 @@ -1061,7 +1061,7 @@ F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4 F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8 F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2 -F test/symlink.test 511db82662446bb0d3619002422760ef8e4b1122 +F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849 F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85 F test/syscall.test f59ba4e25f7ba4a4c031026cc2ef8b6e4b4c639c F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04 @@ -1419,7 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 8a6e4147a680ad6c5fdd588468b6daac82349d2c -R d2cf53f7b50c768b631d5f18bba143b9 -U drh -Z 592370e14c792642f017f87ac074cb77 +P 1c2656c1d37906230edc142d3a4253b16b6e925f +R 6c0824142ba46339a29c32338146479b +U dan +Z e95289d1bfc22539e02b85ec76fd69c7 diff --git a/manifest.uuid b/manifest.uuid index 78b51cd18f..72144560be 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1c2656c1d37906230edc142d3a4253b16b6e925f \ No newline at end of file +4a4385564dd3887a7953820b60c99d6ce289f96a \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index cdbcd2c8e0..81422f215d 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -5955,7 +5955,12 @@ static int mkFullPathname( iOff = sqlite3Strlen30(zOut); zOut[iOff++] = '/'; } - if( (iOff+nPath+1)>nOut ) return SQLITE_CANTOPEN_BKPT; + if( (iOff+nPath+1)>nOut ){ + /* SQLite assumes that xFullPathname() nul-terminates the output buffer + ** even if it returns an error. */ + zOut[iOff] = '\0'; + return SQLITE_CANTOPEN_BKPT; + } sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath); return SQLITE_OK; } @@ -6020,15 +6025,17 @@ static int unixFullPathname( nByte = osReadlink(zIn, zDel, nOut-1); if( nByte<0 ){ rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn); - }else if( zDel[0]!='/' ){ - int n; - for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--); - if( nByte+n+1>nOut ){ - rc = SQLITE_CANTOPEN_BKPT; - }else{ - memmove(&zDel[n], zDel, nByte+1); - memcpy(zDel, zIn, n); - nByte += n; + }else{ + if( zDel[0]!='/' ){ + int n; + for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--); + if( nByte+n+1>nOut ){ + rc = SQLITE_CANTOPEN_BKPT; + }else{ + memmove(&zDel[n], zDel, nByte+1); + memcpy(zDel, zIn, n); + nByte += n; + } } zDel[nByte] = '\0'; } @@ -6037,8 +6044,8 @@ static int unixFullPathname( zIn = zDel; } - if( rc==SQLITE_OK ){ - assert( zIn!=zOut || zIn[0]=='/' ); + assert( rc!=SQLITE_OK || zIn!=zOut || zIn[0]=='/' ); + if( rc==SQLITE_OK && zIn!=zOut ){ rc = mkFullPathname(zIn, zOut, nOut); } if( bLink==0 ) break; diff --git a/test/symlink.test b/test/symlink.test index e9e5f3c305..949102cf8a 100644 --- a/test/symlink.test +++ b/test/symlink.test @@ -181,7 +181,6 @@ do_test 4.4.0 { } {} do_test 4.4.1 { db close - breakpoint sqlite3 db w/test.db db eval { SELECT * FROM t1 } } {hello world}