Message-ID: From: "jarvis24young (@jarvis24young)" To: "postgresql-interfaces/psqlodbc" Date: Wed, 06 May 2026 08:13:00 +0000 Subject: [postgresql-interfaces/psqlodbc] PR #182: Reject invalid SQLPutData lengths List-Id: X-GitHub-Author-Id: 48787405 X-GitHub-Author-Login: jarvis24young X-GitHub-Issue: 182 X-GitHub-Repo: postgresql-interfaces/psqlodbc X-GitHub-State: merged X-GitHub-Type: pull_request X-GitHub-Url: https://github.com/postgresql-interfaces/psqlodbc/pull/182 Content-Type: text/plain; charset=utf-8 ## Summary This patch hardens `SQLPutData()` data-at-execution handling against invalid negative `StrLen_or_Ind` values. `PGAPI_PutData()` previously treated any negative `cbValue` as a length and stored it in `EXEC_used`. That value is later used as the append offset for repeated `SQLPutData()` calls. A caller that supplies an invalid negative length can therefore leave a negative offset in the put-data state, and a subsequent positive chunk can reach the append path with that negative offset. The updated fix keeps the error handling within the existing statement error-code set, per review feedback: - accepts the ODBC sentinel values `SQL_NULL_DATA` and `SQL_DEFAULT_PARAM` - keeps existing `SQL_NTS` handling for character data - rejects other negative lengths using the existing `STMT_INVALID_ARGUMENT_NO` statement error - treats `SQL_DEFAULT_PARAM` like `SQL_NULL_DATA` on the first put-data call so it does not fall through to allocation/copy logic with a negative length - rejects later chunks after a null/default indicator before the LO/non-LO split using the existing `STMT_SEQUENCE_ERROR` This keeps invalid API input from becoming persistent statement state and prevents it from being reused as a buffer offset, without adding new statement error enums or changing the connection/environment diagnostic paths. ## Tests Added regression coverage to `dataatexecution-test` for two public ODBC API paths: ```c SQLPutData(hstmt, "bad", -10); ``` verifies `SQL_ERROR` with the existing `HY024` diagnostic, and: ```c SQLPutData(hstmt, NULL, SQL_NULL_DATA); SQLPutData(hstmt, "x", 1); ``` verifies `SQL_ERROR` with the existing `HY010` diagnostic. Verified in WSL with a clean build copy: ```text cd ~/psqlodbc-pr182-review ./bootstrap ./configure --with-unixodbc=__without_odbc_config \ CFLAGS='-O1 -g -fno-omit-frame-pointer -I/usr/include/postgresql -DSQLCOLATTRIBUTE_SQLLEN -Wall' make -j2 cd test make reset-db LIBODBC=-lodbc make exe/dataatexecution-test LIBODBC=-lodbc ODBCSYSINI=. ODBCINSTINI=./odbcinst.ini ODBCINI=./odbc.ini ./reset-db < sampletables.sql ODBCSYSINI=. ODBCINSTINI=./odbcinst.ini ODBCINI=./odbc.ini ./exe/dataatexecution-test ``` Observed output: ```text connected Result set: 2 3 Parameter Status Fetching result sets for array bound (2 results expected) 1: Result set: 4 2: Result set: 5 Invalid SQLPutData length rejected SQLPutData append after null rejected disconnecting ```