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



Reply via email to