php / php/php-src

PDO inserts NULL byte at position 254 on SQL Server ntext column

Open
#16,901 14 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Bug Extension: pdo_odbc Status: Needs Triage
Dominant language
C
Stars
40.4k
Forks
8.1k
Avg merge
2d 13h
Merged PRs (30d)
96

Description

Description

The following code:

<?php
try {
    $pdo = new PDO('odbc:DRIVER={SQL Server};SERVER=SHS\HS2017,49011;DATABASE=OIDDB', '', '');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $query = 'SELECT name, description, protected, visible, value FROM oidplus_config';
    $stmt = $pdo->query($query);
    $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
    foreach ($results as $row) {
        if (($p = strpos($row['value'],"\0")) !== false) echo "PROBLEM: NULL BYTE FOUND AT ".$row['name']." AT POSITION $p\n";
    }
} catch (PDOException $e) {
    echo "Error: " . $e->getMessage();
}

Resulted in this output:

PROBLEM: NULL BYTE FOUND AT oidplus_private_key AT POSITION 254
PROBLEM: NULL BYTE FOUND AT oidplus_public_key AT POSITION 254

But I expected this output instead:

(Nothing)

I have verified that in the database the NULL byte is not there. In the database, the field has the correct length, in PHP strlen() is 1 byte too much, because of the inserted NULL byte

This seems to be very similar to the bug described at https://bugs.php.net/bug.php?id=74021

The SQL table is created as follows:

USE [OIDDB]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[oidplus_config](
	[name] [nvarchar](50) NOT NULL,
	[value] [ntext] NOT NULL,
	[description] [nvarchar](255) NULL,
	[protected] [bit] NOT NULL,
	[visible] [bit] NOT NULL,
 CONSTRAINT [PK_oidplus_config] PRIMARY KEY CLUSTERED 
(
	[name] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

ALTER TABLE [dbo].[oidplus_config] ADD  DEFAULT ('0') FOR [protected]
GO

ALTER TABLE [dbo].[oidplus_config] ADD  DEFAULT ('0') FOR [visible]
GO
PHP Version

8.4.1 (also tested with 8.3.6)

Operating System

Windows 10

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Run the provided PDO ODBC reproducer against the SQL Server ntext column and inspect the fetched value around position 254. No source file or test is named; done means PDO no longer returns an inserted NULL byte and the fetched string length matches the database value.

Written by the indexing model from the issue text.

Assessment

Tech stack
php, sql
Domain
database
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.