@@ -225,7 +225,10 @@ def _parse_sheet(
225225
226226 # データサイズ検証(DoS対策)
227227 range_rows , range_cols = self ._calculate_range_size (cell_range )
228- if range_rows > config .excel_max_data_rows or range_cols > config .excel_max_data_cols :
228+ if (
229+ range_rows > config .excel_max_data_rows
230+ or range_cols > config .excel_max_data_cols
231+ ):
229232 raise ValueError (
230233 f"データサイズ({ range_rows } 行 × { range_cols } 列)が上限"
231234 f"({ config .excel_max_data_rows } 行 × { config .excel_max_data_cols } 列)を超えています。"
@@ -243,24 +246,39 @@ def _parse_sheet(
243246 if header_range :
244247 header_data = sheet [header_range ]
245248 header_rows_data = self ._normalize_range_data (header_data )
246- all_rows .extend (self ._parse_rows (header_rows_data , include_formatting , merged_cell_map ))
249+ all_rows .extend (
250+ self ._parse_rows (
251+ header_rows_data , include_formatting , merged_cell_map
252+ )
253+ )
247254
248255 # データ範囲を取得(metadata_onlyの場合はスキップ)
249256 if not metadata_only :
250257 range_data = sheet [data_range ]
251258 data_rows_data = self ._normalize_range_data (range_data )
252- all_rows .extend (self ._parse_rows (data_rows_data , include_formatting , merged_cell_map ))
259+ all_rows .extend (
260+ self ._parse_rows (
261+ data_rows_data , include_formatting , merged_cell_map
262+ )
263+ )
253264 else :
254265 # 通常のセル範囲取得(metadata_onlyの場合もヘッダーなしなので取得)
255266 if not metadata_only :
256267 range_data = sheet [cell_range ]
257268 rows_to_process = self ._normalize_range_data (range_data )
258- all_rows .extend (self ._parse_rows (rows_to_process , include_formatting , merged_cell_map ))
269+ all_rows .extend (
270+ self ._parse_rows (
271+ rows_to_process , include_formatting , merged_cell_map
272+ )
273+ )
259274 elif sheet .dimensions :
260275 # シート全体を取得
261276 # データサイズ検証(DoS対策)
262277 sheet_rows , sheet_cols = self ._calculate_range_size (sheet .dimensions )
263- if sheet_rows > config .excel_max_data_rows or sheet_cols > config .excel_max_data_cols :
278+ if (
279+ sheet_rows > config .excel_max_data_rows
280+ or sheet_cols > config .excel_max_data_cols
281+ ):
264282 raise ValueError (
265283 f"シート全体のサイズ({ sheet_rows } 行 × { sheet_cols } 列)が上限"
266284 f"({ config .excel_max_data_rows } 行 × { config .excel_max_data_cols } 列)を超えています。"
@@ -269,22 +287,18 @@ def _parse_sheet(
269287 )
270288
271289 # metadata_onlyの場合はヘッダーのみ取得
290+ rows_to_process = None
272291 if metadata_only and include_header and frozen_rows > 0 :
273292 # ヘッダー行のみ取得
274- for row in sheet .iter_rows (max_row = frozen_rows ):
275- row_data = [
276- self ._parse_cell (cell , include_formatting , merged_cell_map )
277- for cell in row
278- ]
279- all_rows .append (row_data )
293+ rows_to_process = tuple (sheet .iter_rows (max_row = frozen_rows ))
280294 elif not metadata_only :
281295 # 全データを取得
282- for row in sheet .iter_rows ():
283- row_data = [
284- self . _parse_cell ( cell , include_formatting , merged_cell_map )
285- for cell in row
286- ]
287- all_rows . append ( row_data )
296+ rows_to_process = tuple ( sheet .iter_rows ())
297+
298+ if rows_to_process :
299+ all_rows . extend (
300+ self . _parse_rows ( rows_to_process , include_formatting , merged_cell_map )
301+ )
288302
289303 # レスポンス形式の分岐
290304 if include_header :
@@ -452,6 +466,13 @@ def _calculate_range_size(self, range_str: str) -> tuple[int, int]:
452466 start_col_idx = column_index_from_string (start_col )
453467 end_col_idx = column_index_from_string (end_col )
454468
469+ # 逆順序の範囲を検出(セキュリティ対策)
470+ if end_row < start_row or end_col_idx < start_col_idx :
471+ raise ValueError (
472+ f"無効なセル範囲: '{ range_str } '。"
473+ f"範囲は正しい順序で指定してください(例: 'A1:Z100')"
474+ )
475+
455476 rows = end_row - start_row + 1
456477 cols = end_col_idx - start_col_idx + 1
457478
0 commit comments