Thread

Commits

  1. Fix incorrect iteration type in extension_file_exists()

  2. Add paths of extensions to pg_available_extensions

  1. Fix a bug in extension_file_exists()

    Chao Li <li.evan.chao@gmail.com> — 2026-02-09T09:21:17Z

    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/
    
    
    
    
    
  2. Re: Fix a bug in extension_file_exists()

    Heikki Linnakangas <hlinnaka@iki.fi> — 2026-02-09T10:02:10Z

    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
    
    
    
    
    
  3. Re: Fix a bug in extension_file_exists()

    Matheus Alcantara <matheusssilv97@gmail.com> — 2026-02-09T13:19:20Z

    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
    
    
    
    
  4. Re: Fix a bug in extension_file_exists()

    Chao Li <li.evan.chao@gmail.com> — 2026-02-10T00:50:10Z

    
    > 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/