OSDN Git Service

Fix bugs of decoding INI files.
authors_kawamoto <s_kawamoto@users.sourceforge.jp>
Mon, 7 Nov 2011 16:38:59 +0000 (01:38 +0900)
committers_kawamoto <s_kawamoto@users.sourceforge.jp>
Mon, 7 Nov 2011 16:38:59 +0000 (01:38 +0900)
Fix bugs of UTF-8 to UTF-16 API bridge.
Fix bugs of arbitrary code execution.
Add routines for checking UTF-8 redundant representation.
Fix spelling mistakes of filenames.

12 files changed:
FFFTP.vc90.vcproj
FFFTP.vcproj
FFFTP_Eng_Release/FFFTP.exe
FFFTP_English.vc90.vcproj
FFFTP_English.vcproj
OLDregistry.c [moved from OLDregistory.c with 100% similarity]
Release/FFFTP.exe
filelist.c
mbswrapper.c
mbswrapper.h
putty/Release/PuTTY.dll
registry.c [moved from registory.c with 93% similarity]

index a479903..7f15584 100644 (file)
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\registory.c"\r
+                               RelativePath=".\registry.c"\r
                                >\r
                        </File>\r
                        <File\r
index d56ef28..eb93458 100644 (file)
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\registory.c"\r
+                               RelativePath=".\registry.c"\r
                                >\r
                        </File>\r
                        <File\r
index 56b45e8..947983e 100644 (file)
Binary files a/FFFTP_Eng_Release/FFFTP.exe and b/FFFTP_Eng_Release/FFFTP.exe differ
index e1d0fb4..03ed55d 100644 (file)
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\registory.c"\r
+                               RelativePath=".\registry.c"\r
                                >\r
                        </File>\r
                        <File\r
index dcdc984..5919e3a 100644 (file)
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\registory.c"\r
+                               RelativePath=".\registry.c"\r
                                >\r
                        </File>\r
                        <File\r
similarity index 100%
rename from OLDregistory.c
rename to OLDregistry.c
index 4189c08..b7f916a 100644 (file)
Binary files a/Release/FFFTP.exe and b/Release/FFFTP.exe differ
index 4b798fa..c75e28d 100644 (file)
@@ -4905,6 +4905,8 @@ static int ResolvFileInfo(char *Str, int ListType, char *Fname, LONGLONG *Size,
                        Ret = NODE_NONE;\r
                else\r
                        ChangeFnameRemote2Local(Fname, FMAX_PATH);\r
+               // UTF-8の冗長表現によるディレクトリトラバーサル対策\r
+               FixStringM(Fname, Fname);\r
                // 0x5Cが含まれる文字列を扱えないバグ修正\r
                if((_mbscmp(_mbsninc(Fname, _mbslen(Fname) - 1), "/") == 0)\r
                        || (_mbscmp(_mbsninc(Fname, _mbslen(Fname) - 1), "\\") == 0))\r
index 3e55ce0..242837c 100644 (file)
@@ -387,6 +387,166 @@ char* DuplicateWtoA(LPCWSTR lpString, int c)
        return p;\r
 }\r
 \r
+// マルチバイト文字列の冗長表現を修正\r
+// 修正があればTRUEを返す\r
+// 修正後の文字列の長さは元の文字列の長さ以下のためpDstとpSrcに同じ値を指定可能\r
+BOOL FixStringM(LPSTR pDst, LPCSTR pSrc)\r
+{\r
+       BOOL bResult;\r
+       char* p;\r
+       DWORD Code;\r
+       int i;\r
+       char c;\r
+       bResult = FALSE;\r
+       p = (char*)pSrc;\r
+       while(*pSrc != '\0')\r
+       {\r
+               Code = 0;\r
+               if((*pSrc & 0xfe) == 0xfc)\r
+               {\r
+                       i = 5;\r
+                       Code |= (DWORD)*pSrc & 0x01;\r
+               }\r
+               else if((*pSrc & 0xfc) == 0xf8)\r
+               {\r
+                       i = 4;\r
+                       Code |= (DWORD)*pSrc & 0x03;\r
+               }\r
+               else if((*pSrc & 0xf8) == 0xf0)\r
+               {\r
+                       i = 3;\r
+                       Code |= (DWORD)*pSrc & 0x07;\r
+               }\r
+               else if((*pSrc & 0xf0) == 0xe0)\r
+               {\r
+                       i = 2;\r
+                       Code |= (DWORD)*pSrc & 0x0f;\r
+               }\r
+               else if((*pSrc & 0xe0) == 0xc0)\r
+               {\r
+                       i = 1;\r
+                       Code |= (DWORD)*pSrc & 0x1f;\r
+               }\r
+               else if((*pSrc & 0x80) == 0x00)\r
+               {\r
+                       i = 0;\r
+                       Code |= (DWORD)*pSrc & 0x7f;\r
+               }\r
+               else\r
+                       i = -1;\r
+               pSrc++;\r
+               while((*pSrc & 0xc0) == 0x80)\r
+               {\r
+                       i--;\r
+                       Code = Code << 6;\r
+                       Code |= (DWORD)*pSrc & 0x3f;\r
+                       pSrc++;\r
+               }\r
+               if(i != 0)\r
+                       continue;\r
+               else if(Code & 0x7c000000)\r
+               {\r
+                       i = 5;\r
+                       c = (char)(0xfc | (Code >> (6 * i)));\r
+               }\r
+               else if(Code & 0x03e00000)\r
+               {\r
+                       i = 4;\r
+                       c = (char)(0xf8 | (Code >> (6 * i)));\r
+               }\r
+               else if(Code & 0x001f0000)\r
+               {\r
+                       i = 3;\r
+                       c = (char)(0xf0 | (Code >> (6 * i)));\r
+               }\r
+               else if(Code & 0x0000f800)\r
+               {\r
+                       i = 2;\r
+                       c = (char)(0xe0 | (Code >> (6 * i)));\r
+               }\r
+               else if(Code & 0x00000780)\r
+               {\r
+                       i = 1;\r
+                       c = (char)(0xc0 | (Code >> (6 * i)));\r
+               }\r
+               else\r
+               {\r
+                       i = 0;\r
+                       c = (char)Code;\r
+               }\r
+               if(c != *p)\r
+                       bResult = TRUE;\r
+               p++;\r
+               *pDst = c;\r
+               pDst++;\r
+               while(i > 0)\r
+               {\r
+                       i--;\r
+                       c = (char)(0x80 | ((Code >> (6 * i)) & 0x3f));\r
+                       if(c != *p)\r
+                               bResult = TRUE;\r
+                       p++;\r
+                       *pDst = c;\r
+                       pDst++;\r
+               }\r
+       }\r
+       if(*p != '\0')\r
+               bResult = TRUE;\r
+       *pDst = '\0';\r
+       return bResult;\r
+}\r
+\r
+// NULL区切りマルチバイト文字列の冗長表現を修正\r
+// 修正があればTRUEを返す\r
+// 修正後の文字列の長さは元の文字列の長さ以下のためpDstとpSrcに同じ値を指定可能\r
+BOOL FixMultiStringM(LPSTR pDst, LPCSTR pSrc)\r
+{\r
+       BOOL bResult;\r
+       int Length;\r
+       bResult = FALSE;\r
+       while(*pSrc != '\0')\r
+       {\r
+               Length = strlen(pSrc) + 1;\r
+               bResult = bResult | FixStringM(pDst, pSrc);\r
+               pSrc += Length;\r
+               pDst += strlen(pDst) + 1;\r
+       }\r
+       *pDst = '\0';\r
+       return bResult;\r
+}\r
+\r
+// マルチバイト文字列の冗長表現を確認\r
+// 冗長表現があればTRUEを返す\r
+BOOL CheckStringM(LPCSTR lpString)\r
+{\r
+       BOOL bResult;\r
+       char* p;\r
+       bResult = FALSE;\r
+       p = AllocateStringM(strlen(lpString) + 1);\r
+       if(p)\r
+       {\r
+               bResult = FixStringM(p, lpString);\r
+               FreeDuplicatedString(p);\r
+       }\r
+       return bResult;\r
+}\r
+\r
+// NULL区切りマルチバイト文字列の冗長表現を確認\r
+// 冗長表現があればTRUEを返す\r
+BOOL CheckMultiStringM(LPCSTR lpString)\r
+{\r
+       BOOL bResult;\r
+       char* p;\r
+       bResult = FALSE;\r
+       p = AllocateStringM(GetMultiStringLengthM(lpString) + 1);\r
+       if(p)\r
+       {\r
+               bResult = FixMultiStringM(p, lpString);\r
+               FreeDuplicatedString(p);\r
+       }\r
+       return bResult;\r
+}\r
+\r
 // 文字列用に確保したメモリを開放\r
 // リソースIDならば何もしない\r
 void FreeDuplicatedString(void* p)\r
@@ -1857,6 +2017,7 @@ START_ROUTINE
        r = CopyFileW(pw0, pw1, bFailIfExists);\r
 END_ROUTINE\r
        FreeDuplicatedString(pw0);\r
+       FreeDuplicatedString(pw1);\r
        return r;\r
 }\r
 \r
index ec153ed..6e5e6ce 100644 (file)
@@ -238,6 +238,10 @@ wchar_t* DuplicateMtoWMultiStringBuffer(LPCSTR lpString, int size);
 char* DuplicateWtoM(LPCWSTR lpString, int c);\r
 wchar_t* DuplicateAtoW(LPCSTR lpString, int c);\r
 char* DuplicateWtoA(LPCWSTR lpString, int c);\r
+BOOL FixStringM(LPSTR pDst, LPCSTR pSrc);\r
+BOOL FixMultiStringM(LPSTR pDst, LPCSTR pSrc);\r
+BOOL CheckStringM(LPCSTR lpString);\r
+BOOL CheckMultiStringM(LPCSTR lpString);\r
 void FreeDuplicatedString(void* p);\r
 \r
 int WINAPI WinMainM(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);\r
index 4ea2026..af44daf 100644 (file)
Binary files a/putty/Release/PuTTY.dll and b/putty/Release/PuTTY.dll differ
similarity index 93%
rename from registory.c
rename to registry.c
index 931c89f..1bb3b8b 100644 (file)
@@ -1083,6 +1083,9 @@ void SaveSettingsToFile(void)
 {\r
        char Tmp[FMAX_PATH*2];\r
        char Fname[FMAX_PATH+1];\r
+       // 任意のコードが実行されるバグ修正\r
+       char CurDir[FMAX_PATH+1];\r
+       char SysDir[FMAX_PATH+1];\r
 \r
        if(RegType == REGTYPE_REG)\r
        {\r
@@ -1090,9 +1093,24 @@ void SaveSettingsToFile(void)
                if(SelectFile(GetMainHwnd(), Fname, MSGJPN286, MSGJPN287, "reg", OFN_EXTENSIONDIFFERENT | OFN_OVERWRITEPROMPT, 1) == TRUE)\r
                {\r
                        sprintf(Tmp, "/e \x22%s\x22 HKEY_CURRENT_USER\\Software\\sota\\FFFTP", Fname);\r
-                       if(ShellExecute(NULL, "open", "regedit", Tmp, ".", SW_SHOW) <= (HINSTANCE)32)\r
+                       // 任意のコードが実行されるバグ修正\r
+//                     if(ShellExecute(NULL, "open", "regedit", Tmp, ".", SW_SHOW) <= (HINSTANCE)32)\r
+//                     {\r
+//                             MessageBox(NULL, MSGJPN285, "FFFTP", MB_OK);\r
+//                     }\r
+                       if(GetCurrentDirectory(FMAX_PATH, CurDir) > 0)\r
                        {\r
-                               MessageBox(NULL, MSGJPN285, "FFFTP", MB_OK);\r
+                               if(GetSystemDirectory(SysDir, FMAX_PATH) > 0)\r
+                               {\r
+                                       if(SetCurrentDirectory(SysDir))\r
+                                       {\r
+                                               if(ShellExecute(NULL, "open", "regedit", Tmp, ".", SW_SHOW) <= (HINSTANCE)32)\r
+                                               {\r
+                                                       MessageBox(NULL, MSGJPN285, "FFFTP", MB_OK);\r
+                                               }\r
+                                               SetCurrentDirectory(CurDir);\r
+                                       }\r
+                               }\r
                        }\r
                }\r
        }\r
@@ -1122,6 +1140,9 @@ int LoadSettingsFromFile(void)
        int Ret;\r
        char Tmp[FMAX_PATH*2];\r
        char Fname[FMAX_PATH+1];\r
+       // 任意のコードが実行されるバグ修正\r
+       char CurDir[FMAX_PATH+1];\r
+       char SysDir[FMAX_PATH+1];\r
 \r
        Ret = NO;\r
        strcpy(Fname, "");\r
@@ -1130,15 +1151,36 @@ int LoadSettingsFromFile(void)
                if((strlen(Fname) >= 5) && (_stricmp(&Fname[strlen(Fname)-4], ".reg") == 0))\r
                {\r
                        sprintf(Tmp, "\x22%s\x22", Fname);\r
-                       if(ShellExecute(NULL, "open", "regedit", Tmp, ".", SW_SHOW) <= (HINSTANCE)32)\r
-                       {\r
-                               MessageBox(NULL, MSGJPN285, "FFFTP", MB_OK);\r
-                       }\r
-                       else\r
-                       {\r
-                               Ret = YES;\r
-                               /* レジストリエディタが終了するのを待つ */\r
+                       // 任意のコードが実行されるバグ修正\r
+//                     if(ShellExecute(NULL, "open", "regedit", Tmp, ".", SW_SHOW) <= (HINSTANCE)32)\r
+//                     {\r
+//                             MessageBox(NULL, MSGJPN285, "FFFTP", MB_OK);\r
+//                     }\r
+//                     else\r
+//                     {\r
+//                             Ret = YES;\r
+//                             /* レジストリエディタが終了するのを待つ */\r
 //                             WaitForSingleObject(Info.hProcess, INFINITE);\r
+//                     }\r
+                       if(GetCurrentDirectory(FMAX_PATH, CurDir) > 0)\r
+                       {\r
+                               if(GetSystemDirectory(SysDir, FMAX_PATH) > 0)\r
+                               {\r
+                                       if(SetCurrentDirectory(SysDir))\r
+                                       {\r
+                                               if(ShellExecute(NULL, "open", "regedit", Tmp, ".", SW_SHOW) <= (HINSTANCE)32)\r
+                                               {\r
+                                                       MessageBox(NULL, MSGJPN285, "FFFTP", MB_OK);\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       Ret = YES;\r
+                                                       /* レジストリエディタが終了するのを待つ */\r
+//                                                     WaitForSingleObject(Info.hProcess, INFINITE);\r
+                                               }\r
+                                               SetCurrentDirectory(CurDir);\r
+                                       }\r
+                               }\r
                        }\r
                }\r
                else if((strlen(Fname) >= 5) && (_stricmp(&Fname[strlen(Fname)-4], ".ini") == 0))\r
@@ -2273,9 +2315,9 @@ static int ReadStringFromReg(void *Handle, char *Name, char *Str, DWORD Size)
        int Sts;\r
        char *Pos;\r
        // UTF-8対応\r
+       DWORD TempSize;\r
        char* pa0;\r
        wchar_t* pw0;\r
-       DWORD TempSize;\r
 \r
        Sts = FFFTP_FAIL;\r
        if(TmpRegType == REGTYPE_REG)\r
@@ -2298,6 +2340,16 @@ static int ReadStringFromReg(void *Handle, char *Name, char *Str, DWORD Size)
 //                     Sts = FFFTP_SUCCESS;\r
                        switch(IniKanjiCode)\r
                        {\r
+                       case KANJI_NOCNV:\r
+                               TempSize = min1(Size-1, strlen(Pos));\r
+                               TempSize = StrReadIn(Pos, TempSize, Str);\r
+                               *(Str + TempSize) = NUL;\r
+                               Sts = FFFTP_SUCCESS;\r
+                               if(!CheckStringM(Str))\r
+                                       break;\r
+                               Str = Str;\r
+                               // UTF-8ではない可能性がある\r
+                               // Shift_JISとみなす\r
                        case KANJI_SJIS:\r
                                if(pa0 = AllocateStringA(Size * 4))\r
                                {\r
@@ -2315,12 +2367,6 @@ static int ReadStringFromReg(void *Handle, char *Name, char *Str, DWORD Size)
                                        FreeDuplicatedString(pa0);\r
                                }\r
                                break;\r
-                       case KANJI_NOCNV:\r
-                               Size = min1(Size-1, strlen(Pos));\r
-                               Size = StrReadIn(Pos, Size, Str);\r
-                               *(Str + Size) = NUL;\r
-                               Sts = FFFTP_SUCCESS;\r
-                               break;\r
                        }\r
                }\r
        }\r
@@ -2378,6 +2424,10 @@ static int ReadMultiStringFromReg(void *Handle, char *Name, char *Str, DWORD Siz
 {\r
        int Sts;\r
        char *Pos;\r
+       // UTF-8対応\r
+       DWORD TempSize;\r
+       char* pa0;\r
+       wchar_t* pw0;\r
 \r
        Sts = FFFTP_FAIL;\r
        if(TmpRegType == REGTYPE_REG)\r
@@ -2393,10 +2443,42 @@ static int ReadMultiStringFromReg(void *Handle, char *Name, char *Str, DWORD Siz
        {\r
                if((Pos = ScanValue(Handle, Name)) != NULL)\r
                {\r
-                       Size = min1(Size-1, strlen(Pos));\r
-                       Size = StrReadIn(Pos, Size, Str);\r
-                       *(Str + Size) = NUL;\r
-                       Sts = FFFTP_SUCCESS;\r
+                       // UTF-8対応\r
+//                     Size = min1(Size-1, strlen(Pos));\r
+//                     Size = StrReadIn(Pos, Size, Str);\r
+//                     *(Str + Size) = NUL;\r
+//                     Sts = FFFTP_SUCCESS;\r
+                       switch(IniKanjiCode)\r
+                       {\r
+                       case KANJI_NOCNV:\r
+                               TempSize = min1(Size-1, strlen(Pos));\r
+                               TempSize = StrReadIn(Pos, TempSize, Str);\r
+                               *(Str + TempSize) = NUL;\r
+                               Sts = FFFTP_SUCCESS;\r
+                               if(!CheckMultiStringM(Str))\r
+                                       break;\r
+                               // UTF-8ではない可能性がある\r
+                               // Shift_JISとみなす\r
+                       case KANJI_SJIS:\r
+                               if(pa0 = AllocateStringA(Size * 4))\r
+                               {\r
+                                       if(pw0 = AllocateStringW(Size * 4 * 4))\r
+                                       {\r
+                                               TempSize = min1((Size * 4) - 2, strlen(Pos));\r
+                                               TempSize = StrReadIn(Pos, TempSize, pa0);\r
+                                               *(pa0 + TempSize) = NUL;\r
+                                               *(pa0 + TempSize + 1) = NUL;\r
+                                               AtoWMultiString(pw0, Size * 4 * 4, pa0);\r
+                                               WtoMMultiString(Str, Size, pw0);\r
+                                               TerminateStringM(Str, Size);\r
+                                               TerminateStringM(Str, Size - 1);\r
+                                               Sts = FFFTP_SUCCESS;\r
+                                               FreeDuplicatedString(pw0);\r
+                                       }\r
+                                       FreeDuplicatedString(pa0);\r
+                               }\r
+                               break;\r
+                       }\r
                }\r
        }\r
        return(Sts);\r