Heap OOB read (scanbuf-1) and empty prosrc when EOF immediately follows AS/IS in CREATE FUNCTION (oracle mode)

Offen
#2,940 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Maintainer antworten meist innerhalb von 1 Tag

@zhaohai666 arbeitet bereits daran.

Seit 26.10.2026.

  • #2942 von @zhaohai666 — offen

Bewertung

Schwierigkeit
3/5
Geschätzter Aufwand
1-2 Tage
Anfängerfreundlichkeit
35/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Veraltet
Tech-Stack
c, postgresql
Bereich
backend, database

Rechercherichtung

Start in src/backend/oracle_parser/liboracle_parser.c and read set_oracle_plsql_body(), including the PACKAGE/TYPE BODY branch with the similar scan loop. Reproduce the EOF case in oracle mode using the SQL shown in the issue, then inspect the parser behavior and relevant tests. Done means EOF immediately after AS/IS reports a syntax error without an out-of-bounds read or creating a function with empty prosrc.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

Environment
  • IvorySQL master @ 2c5e8dd (self-built from source)
  • Mode: oracle (ivorysql.database_mode = oracle)
Steps to reproduce
-- oracle-mode port; note: no body, no terminator, EOF right after AS
CREATE OR REPLACE FUNCTION f() RETURN int AS
Actual behavior
WARNING:  compilation error
HINT:  syntax error at end of input
CREATE FUNCTION

The statement succeeds and an invalid function is created whose prosrc is the empty string:

SELECT length(prosrc) FROM pg_proc WHERE proname = 'f';
 length | 0

Calling it then fails with ERROR: function f is in invalid state.

For comparison, a properly terminated function keeps its source
(prosrc = 'BEGIN RETURN 1; END', length 19).

Expected behavior

A syntax error (matching PostgreSQL semantics), and under no circumstances an out-of-bounds read.

Root cause analysis

In src/backend/oracle_parser/liboracle_parser.c, set_oracle_plsql_body() initializes the body position sentinel:

set_oracle_plsql_bodystart(yyscanner, -1, 0);   /* body_start = -1 */

When EOF arrives immediately after AS/IS, cur_token == 0 on entry, so the token-scanning loop

while (cur_token != 0)
{
    if (beginpos < 0)
        beginpos = *llocp;
    ...
}

never executes and beginpos stays -1. The trailing guard

if ((cur_token == ';' && blocklevel == 0 && ...) ||
    (cur_token == 0 && blocklevel > 0))

is also skipped (both disjuncts false), and execution falls through to:

lvalp->core_yystype.str = pstrdup(yyextra->core_yy_extra.scanbuf + beginpos);  /* scanbuf - 1 */

i.e. pstrdup(scanbuf - 1) — a 1-byte heap buffer underflow read (the scan buffer is palloc(slen + 2)). Under ASAN this is a heap-buffer-underflow; in normal builds the byte happens to be \0, producing an empty string that is handed to the grammar as the function body SCONST, which is why the DDL silently "succeeds" with an empty prosrc.

The same pattern exists in the PACKAGE/TYPE BODY branch of the same function (pstrdup(... scanbuf + beginpos) after an identically structured loop, ~120 lines below).

Suggested fix

When cur_token == 0 && blocklevel == 0 on entry (or after the loop), report a proper syntax error instead of synthesizing an SCONST token from scanbuf + beginpos; alternatively guard beginpos >= 0 before the pstrdup.

Vorherrschende Sprache
C
Sterne
1.1k
Forks
232
Ø Merge
2 T. 3 Std.
Gemergte PRs (30 T.)
8

Entwicklungsumgebung

Dieses Projekt bietet weder Dev-Container noch Dockerfile noch Beitragsleitfaden – die Einrichtung liegt bei Ihnen. Beginnen Sie mit der README; die allgemeinen Schritte stehen in unserem Leitfaden für den ersten Beitrag.

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus IvorySQL/IvorySQL

Alle Issues in IvorySQL/IvorySQL

Ähnliche Issues

Weitere Issues zu C

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.