2014-04-04 5 views
5

다음은 플랫 파일에서 데이터를 가져와 SQL Server에 삽입하는 코드입니다. 예외 (Index was outside the bounds of the array)가 생성됩니다. 당신의 라인 일 미만 세 가지 요소 세미콜론으로 구분이 있기 때문에인덱스가 배열 예외 범위를 벗어났습니다

string path = string.Concat(Server.MapPath("~/TempFiles/"), Fileupload1.FileName);      
string text = System.IO.File.ReadAllText(path);    
string[] lines = text.Split(' ');         
con.Open();     
SqlCommand cmd = new SqlCommand();     
string[] Values = new string[3];         
foreach (string line1 in lines)     
{      
    Values = line1.Split(';');           
    string query = "INSERT INTO demooo VALUES ('" + Values[0] + "','" + Values[1] + "','" + Values[2] + "')";      
    cmd = new SqlCommand(query,con);      
    cmd.ExecuteNonQuery();     
} 

답변

2

예외가 발생합니다. ValuesString이라는 세 개의 요소로 구성된 배열로 선언하더라도 변수에 영향을 미치면 String.Split() 함수의 결과에 영향을 미치게됩니다. 배열의 길이는 반환 된 배열의 길이와 같습니다. 코드가 적 으면 코드가 확실히 실패합니다. 이 일이 안이라면

난 당신이 디버깅을 돕기 위해 코드에서 주장을 제안한다

// ... 
Values = line1.Split(';'); 
// the following will make the debugger stop execution if line.Length is smaller than 3 
Debug.Assert(line1.Length >= 3); 
// ... 

가 보조 노트로서, 나는이 배치 INSERT 훨씬 더 효율적으로 될 것입니다 만들기 언급해야한다. 또한 cmd 변수 선언 및 다시 작성 방법이 올바르지 않습니다. 마지막으로 값에 String.Replace으로 전화하여 아포 스트로피가 두 배가되는지 확인해야합니다. 그렇지 않으면 SQL 주입 공격에 대한 코드가 열리게됩니다.

2

코드가 실행시 행동 방법에 대한 몇 가지 세부 사항 :

루프 외부에서 만든 것 SqlCommand도 사용되지 얻을 않겠다고 값이 덮어지고 유지하는 방법과 유사
// This line declares a variable named Values and sets its value to 
// a new array of strings. However, this new array is never used 
// because the loop overwrites Values with a new array before doing 
// anything else with it. 
string[] Values = new string[3];         
foreach (string line1 in lines)     
{      
    Values = line1.Split(';');   
// At this point in the code, whatever was previously stored in Values has been 
// tossed on the garbage heap, and Values now contains a brand new array containing 
// the results of splitting line1 on semicolons. 
// That means that it is no longer safe to assume how many elements the Values array has. 
// For example, if line1 is blank (which often happens at the end of a text file), then 
// Values will be an empty array, and trying to get anything out of it will throw an 
// exception         
    string query = "INSERT INTO demooo VALUES ('" + Values[0] + "','" + Values[1] + "','" + Values[2] + "')";      
    cmd = new SqlCommand(query,con);      
    cmd.ExecuteNonQuery();     
} 

. 이 두 선언을 모두 루프 안에 넣는 것이 안전합니다. 다음 코드는이를 수행하고 사용 가능한 값의 수를 줄에서 검색했는지 확인하기 위해 몇 가지 오류 검사를 추가합니다. 길지 않은 행은 건너 뜁니다. 괜찮 으면, 좀 더 복잡한 오류 처리 코드를 만들어야 할 수도 있습니다.

foreach(string line in lines) 
{ 
    string[] values = line.split[';']; 
    if(values.Length >= 3) 
    { 
     string query = "INSERT INTO demooo VALUES ('" + Values[0] + "','" + Values[1] + "','" + Values[2] + "')";  
     using (SqlCommand command = new SqlCommand(query, con)) 
     { 
      cmd.ExecuteNonQuery(); 
     } 
    } 
} 

위의 코드는 웹 응용 프로그램과 같이 사용하는 경우 해커에게 취약 할 수 있습니다. 이처럼 보였다 파일을 처리 한 경우 서버로 전송받을 수있는 어떤 명령에 대한 생각 :

1;2;3 
4;5;6 
7;8;9') DROP TABLE demooo SELECT DATALENGTH('1  

더 안전한 옵션은 이러한 종류의 공격에 대해 보호하는 데 도움이됩니다 매개 변수화 된 쿼리를 사용하는 것입니다. 이들은 인수와 명령을 분리하여 SQL 코드와 같은 인수 값을 전달하지 못하게합니다. 이렇게 설정하는 방법의 예는 다음과 같습니다.

string query = "INSERT INTO demooo VALUES (@val1, @val2, @val3); 
using (var command = new SqlCommand(query, con)) 
{ 
    command.Parameters.AddWithValue("@val1", Values[0]); 
    command.Parameters.AddWithValue("@val2", Values[1]); 
    command.Parameters.AddWithValue("@val3", Values[2]); 
    command.ExecuteNonQuery(); 
} 
+0

+1은 SQL 주입을 언급합니다. 그러나 OP의 질문에있는 텍스트는 공백으로 구분되어 있으므로 (예 : 줄 바꿈이 아닌 경우)이 유형의 공격이 훨씬 어려워집니다. –

+0

사실 나는 OP가 배치 삽입을 대신하는 것이 더 좋을 것이라고 생각합니다. 그래도 +1은 아주 자세하게 대답합니다. – Crono

1

시도해보십시오.

string path = string.Concat(Server.MapPath("~/TempFiles/"), Fileupload1.FileName); 
string text = System.IO.File.ReadAllText(path); 
string[] lines = text.Split(' '); 
con.Open(); 
string[] Values; 
foreach (string line1 in lines) 
{ 
    Values = line1.Split(';'); 

    if (Values.Length >= 3) 
    { 
     string query = "INSERT INTO demooo VALUES ('" + Values[0] + "','" + Values[1] + "','" + Values[2] + "')"; 
    } 
    else 
    { 
     //Some error occured 
    } 

    using (var cmd = new SqlCommand(query,con)) 
    { 
     cmd.ExecuteNonQuery(); 
    } 
} 
+1

'> ='을 의미합니다. –

+0

@MrLister 그래도 여전히 나쁜 충고입니다. IMHO. 이렇게하면 손상된 파일이나 가능성이있는 파일에 대한 단서를 제공하는 대신 4 개 미만의 값으로 줄을 건너 뜁니다. 한 줄에 세미콜론으로 구분 된 값이 4 개 미만인 것은 발생하지 않아야한다고 가정하는 것이 안전하다고 생각합니다. – Crono

+1

그래서 다른 부분이 있습니다. 해당 오류 메시지를 else 절에 추가 할 수 있습니다. – MoraRockey

관련 문제