security: KVE-2026-2345 승인 후 검증 실패 취소와 장바구니 병합 사전 검사
모바일 이니시스 승인 전 장바구니를 검증하고 승인 후 실패는 서버 세션으로 확인한 거래의 취소 결과를 기록한다. 기존 장바구니와 병합할 가격·수량 및 구매 자격도 변경 전에 확인한다. 공통 규칙 46개, SQLite 및 모의 PG 후속 회귀 25개와 PHP 문법 검사를 통과했다. 실제 MySQL·PG 통합 및 동시성 검증은 별도로 필요하다.
This commit is contained in:
1 parent
6d4e75e1c9
commit
560aa0af47
9 files changed
+315
-15
No files matched your search
@@ -135,6 +135,47 @@ function shop_validate_cart_request($post, $multi = false)
|
||||
return array('error' => $products ? '' : $error, 'products' => $products);
|
||||
}
|
||||
|
||||
// 기존 행과 합친 결과도 삭제/UPDATE 전에 모든 상품에 대해 확인한다.
|
||||
// 동시 요청과 SQL 실패의 원자성까지 보장하는 잠금/트랜잭션은 아니다.
|
||||
function shop_validate_cart_merge($cart_id, $products, $direct = false, $replace = false)
|
||||
{
|
||||
global $g5;
|
||||
$cart_id = sql_escape_string($cart_id);
|
||||
foreach ($products as $it_id => $product) {
|
||||
$id = sql_escape_string($it_id);
|
||||
$rows = array();
|
||||
if (!$replace) {
|
||||
$exclude = $direct ? ' and ct_direct <> 1 ' : '';
|
||||
$result = sql_query(" select * from {$g5['g5_shop_cart_table']} where od_id = '$cart_id' and it_id = '$id' and ct_status = '쇼핑' $exclude order by ct_id asc ");
|
||||
while ($row = sql_fetch_array($result))
|
||||
$rows[] = $row;
|
||||
}
|
||||
$rows = array_merge($rows, $product['rows']);
|
||||
list($item, $options) = shop_cart_option_data($it_id);
|
||||
$validated = shop_validate_cart_rows($item, $options, $rows, true);
|
||||
if ($validated['error'] !== '')
|
||||
return $validated['error'];
|
||||
|
||||
// 바로구매에서는 다른 장바구니가 선택해 둔 수량도 선삭제 전에 검사한다.
|
||||
if ($direct) {
|
||||
$quantities = array();
|
||||
foreach ($rows as $row) {
|
||||
$key = $row['io_type'].':'.$row['io_id'];
|
||||
$quantities[$key] = isset($quantities[$key]) ? $quantities[$key] + $row['ct_qty'] : $row['ct_qty'];
|
||||
}
|
||||
foreach ($product['rows'] as $row) {
|
||||
$io_id = sql_escape_string($row['io_id']);
|
||||
$type = (int) $row['io_type'];
|
||||
$reserved = sql_fetch(" select SUM(ct_qty) as cnt from {$g5['g5_shop_cart_table']} where od_id <> '$cart_id' and it_id = '$id' and io_id = '$io_id' and io_type = '$type' and ct_stock_use = 0 and ct_status = '쇼핑' and ct_select = '1' ");
|
||||
$stock = $row['io_id'] === '' ? get_it_stock_qty($it_id) : get_option_stock_qty($it_id, $row['io_id'], $type);
|
||||
if ($quantities[$type.':'.$row['io_id']] + (int) $reserved['cnt'] > $stock)
|
||||
return '상품 또는 옵션의 재고수량이 부족합니다.';
|
||||
}
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
// 주문 준비/확정 시에는 선택된 행만 검증하여 보조옵션 단독 선택과 과거 조작 행도 차단한다.
|
||||
function shop_validate_order_cart($cart_id)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user