Обсуждение: Fix a bug in extension_file_exists()

Поиск
Список
Период
Сортировка

Fix a bug in extension_file_exists()

От
Chao Li
Дата:
Hi,

I just noticed a bug in extension_file_exists():

```
bool
extension_file_exists(const char *extensionName)
{
    bool        result = false;
    List       *locations;
    DIR           *dir;
    struct dirent *de;

    locations = get_extension_control_directories();

    foreach_ptr(char, location, locations) // <== Here type char is wrong
    {
        dir = AllocateDir(location);
```

get_extension_control_directories() returns a list of ExtensionLocation, but the loop iterates it as if it contained
char*, which is incorrect. As a result, AllocateDir() and ReadDir() are called with the wrong type. 

This bug is only triggered on an error path, when PostgreSQL is deciding whether to emit a hint. For example:
```
evantest=# create function f() returns int LANGUAGE plpython3u as $$return 1$$;
ERROR:  language "plpython3u" does not exist
```
No hint is printed.

With this patch applied:
```
evantest=# create function f() returns int LANGUAGE plpython3u as $$return 1$$;
ERROR:  language "plpython3u" does not exist
HINT:  Use CREATE EXTENSION to load the language into the database.
```
So the hint is shown as intended.

Attached is a patch fixing the iteration to use ExtensionLocation and location->loc consistently.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/





Вложения

Re: Fix a bug in extension_file_exists()

От
Heikki Linnakangas
Дата:
On 09/02/2026 11:21, Chao Li wrote:
> I just noticed a bug in extension_file_exists():
> 
> ```
> bool
> extension_file_exists(const char *extensionName)
> {
>     bool        result = false;
>     List       *locations;
>     DIR           *dir;
>     struct dirent *de;
> 
>     locations = get_extension_control_directories();
> 
>     foreach_ptr(char, location, locations) // <== Here type char is wrong
>     {
>         dir = AllocateDir(location);
> ```
> 
> get_extension_control_directories() returns a list of ExtensionLocation, but the loop iterates it as if it contained
char*, which is incorrect. As a result, AllocateDir() and ReadDir() are called with the wrong type.
 
> 
> This bug is only triggered on an error path, when PostgreSQL is deciding whether to emit a hint. For example:
> ```
> evantest=# create function f() returns int LANGUAGE plpython3u as $$return 1$$;
> ERROR:  language "plpython3u" does not exist
> ```
> No hint is printed.
> 
> With this patch applied:
> ```
> evantest=# create function f() returns int LANGUAGE plpython3u as $$return 1$$;
> ERROR:  language "plpython3u" does not exist
> HINT:  Use CREATE EXTENSION to load the language into the database.
> ```
> So the hint is shown as intended.
> 
> Attached is a patch fixing the iteration to use ExtensionLocation and location->loc consistently.

Yep, good catch. This went wrong in commit f3c9e341cd, which changed the 
type of objects in the list from "char *" to "ExtensionLocation *". So 
this is master only, stable branches are not affected.

I will push the fix shortly, thanks!

- Heikki




Re: Fix a bug in extension_file_exists()

От
Matheus Alcantara
Дата:
On 09/02/26 07:02, Heikki Linnakangas wrote:
> On 09/02/2026 11:21, Chao Li wrote:
>> I just noticed a bug in extension_file_exists():
>>
>> ```
>> bool
>> extension_file_exists(const char *extensionName)
>> {
>>     bool        result = false;
>>     List       *locations;
>>     DIR           *dir;
>>     struct dirent *de;
>>
>>     locations = get_extension_control_directories();
>>
>>     foreach_ptr(char, location, locations) // <== Here type char is 
>> wrong
>>     {
>>         dir = AllocateDir(location);
>> ```
>>
>> get_extension_control_directories() returns a list of 
>> ExtensionLocation, but the loop iterates it as if it contained char 
>> *, which is incorrect. As a result, AllocateDir() and ReadDir() are 
>> called with the wrong type.
>>
>> This bug is only triggered on an error path, when PostgreSQL is 
>> deciding whether to emit a hint. For example:
>> ```
>> evantest=# create function f() returns int LANGUAGE plpython3u as $ 
>> $return 1$$;
>> ERROR:  language "plpython3u" does not exist
>> ```
>> No hint is printed.
>>
>> With this patch applied:
>> ```
>> evantest=# create function f() returns int LANGUAGE plpython3u as $ 
>> $return 1$$;
>> ERROR:  language "plpython3u" does not exist
>> HINT:  Use CREATE EXTENSION to load the language into the database.
>> ```
>> So the hint is shown as intended.
>>
>> Attached is a patch fixing the iteration to use ExtensionLocation 
>> and location->loc consistently.
> 
> Yep, good catch. This went wrong in commit f3c9e341cd, which changed 
> the type of objects in the list from "char *" to "ExtensionLocation 
> *". So this is master only, stable branches are not affected.
> 
> I will push the fix shortly, thanks!
>
Sorry, I miss this change.

Thanks for the patch Chao and Heikki for committing.


-- 
Matheus Alcantara
EDB: https://www.enterprisedb.com



Re: Fix a bug in extension_file_exists()

От
Chao Li
Дата:

> On Feb 9, 2026, at 18:02, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
>
> On 09/02/2026 11:21, Chao Li wrote:
>> I just noticed a bug in extension_file_exists():
>> ```
>> bool
>> extension_file_exists(const char *extensionName)
>> {
>> bool result = false;
>> List   *locations;
>> DIR   *dir;
>> struct dirent *de;
>> locations = get_extension_control_directories();
>> foreach_ptr(char, location, locations) // <== Here type char is wrong
>> {
>> dir = AllocateDir(location);
>> ```
>> get_extension_control_directories() returns a list of ExtensionLocation, but the loop iterates it as if it contained
char*, which is incorrect. As a result, AllocateDir() and ReadDir() are called with the wrong type. 
>> This bug is only triggered on an error path, when PostgreSQL is deciding whether to emit a hint. For example:
>> ```
>> evantest=# create function f() returns int LANGUAGE plpython3u as $$return 1$$;
>> ERROR:  language "plpython3u" does not exist
>> ```
>> No hint is printed.
>> With this patch applied:
>> ```
>> evantest=# create function f() returns int LANGUAGE plpython3u as $$return 1$$;
>> ERROR:  language "plpython3u" does not exist
>> HINT:  Use CREATE EXTENSION to load the language into the database.
>> ```
>> So the hint is shown as intended.
>> Attached is a patch fixing the iteration to use ExtensionLocation and location->loc consistently.
>
> Yep, good catch. This went wrong in commit f3c9e341cd, which changed the type of objects in the list from "char *" to
"ExtensionLocation*". So this is master only, stable branches are not affected. 
>
> I will push the fix shortly, thanks!
>
> - Heikki
>

Thanks for pushing.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/