Make WordPress Core

Opened 10 years ago

Last modified 2 months ago

#36738 assigned defect (bug)

No validation for $post_date_gmt parameter

Reported by: latz's profile Latz Owned by: paulbonneau's profile paulbonneau
Milestone: Future Release Priority: normal
Severity: normal Version: 3.5
Component: Posts, Post Types Keywords: has-test-info good-first-bug has-patch has-unit-tests
Focuses: Cc:

Description

1) When publishing a post via wp_insert_post()and the $post_date_gmt parameter has a wrong format it's silently set to 0000-00-00 00:00:00.

2) If $post_date is omitted in the parameter array WP tries to determine it from $post_date_gmt. A wrong formatted $post_date_gmt leads to a post_date of 1970-01-01 00:00:00.

Just like $post_dateit should throw an error to give a programmer the right hint for his malfunctioning code.

Attachments (2)

36738.diff (1.4 KB) - added by Latz 10 years ago.
36738-02092025.diff (5.1 KB) - added by paulbonneau 2 months ago.

Download all attachments as: .zip

Change History (18)

@Latz
10 years ago

#1 @Latz
10 years ago

  • Keywords has-patch added

#2 @Latz
10 years ago

Realted: #36595

#3 @SirLouen
3 months ago

  • Keywords needs-testing has-test-info good-first-bug added; has-patch removed
  • Version changed from 4.5.1 to 3.5

Looking at the current code, I think this has not been fixed yet.

The patch is not completely valid, ideally we should be refactoring the code to use the current version of wp_resolve_post_date to serve for both versions (if reproducible)

If anyone wants to do a patch, please, first do a reproduction report before sending the patch.

Last edited 3 months ago by SirLouen (previous) (diff)

#4 @paulbonneau
2 months ago

Hello @SirLouen,

The two behaviors reported in @Latz's first message are still present. I can only reproduce them by adding code via a plugin.

Reproduction Report

Environment

Server: Apache (Linux)
WordPress: 6.9-alpha-60093-src
Browser: Chrome 139.0.7258.155
OS: Mac Os 15.4.1 (24E263)
Theme: Twenty Twenty-Five
Plugins: Only my custom reproduction plugin (see below)

Steps

  1. create a folder in wp-content/plugins named 36738-bug-test-reproducer
  2. create a file 36738-bug-test-reproducer.php in the previously created folder
  3. copy the following code in the previously created file :
    <?php
    /**
     * @package 36738-bug-test-reproducer
     * @version 1.7.2
     */
    /*
    Plugin Name: 36738 bug test reproducer
    Plugin URI: 
    Description: A plugin to help reproduce the bugs in this ticket https://core.trac.wordpress.org/ticket/36738
    Author: Test
    Version: 1.0.0
    Author URI: #
    Text Domain: 36738-bug-test-reproducer
    */
    
    // Do not load directly.
    if ( ! defined( 'ABSPATH' ) ) {
        die();
    }
    
    add_action('admin_init', function(){
        if (filter_input(INPUT_GET, 'reproduce_1')) {
            wp_insert_post([
                'post_title' => 'test ' . uniqid(),
                'post_date' => '2025-01-23 23:00:00',
                'post_date_gmt' => 'wrong_format',
                'post_content' => ''
            ]);
        }
        if (filter_input(INPUT_GET, 'reproduce_2')) {
            wp_insert_post([
                'post_title' => 'test ' . uniqid(),
                'post_date_gmt' => 'wrong_format',
                'post_content' => ''
            ]);
        }
    });
    
  4. In your WordPress admin dashboard got to Plugins and activate the 36738 bug test reproducer plugin
  5. Now you can use the followings URL to reproduce @Latz cases :
    1. Case 1) : [YOUR_WORDPRESS_URL]/wp-admin/?reproduce_1=1
    2. Case 2) : [YOUR_WORDPRESS_URL]/wp-admin/?reproduce_2=1
  6. Each time an url is visited, a new post is inserted in database and visible in Posts

Analysis

@SirLouen in your answer you said :

ideally we should be refactoring the code to use the current version of wp_resolve_post_date to serve for both versions

  • I don't think we can use wp_resolve_post_date to serve post_date_gmt in wp_insert_post the same way post_date is served because :
    1. wp_resolve_post_date is explicitly waiting for a post_date in first argument and a post_date_gmt in the second argument;
    2. the way post_date and post_date_gmt are handled in wp_insert_post means that, the check on post_date_gmt with wp_resolve_post_date would need to be added before the check on post_date with the same function. Looking at the current code this would introduce a bit of duplication and will result in a messier wp_insert_post function.

Before modifying the behavior of this part of the code I would like to be sure what is the desired behavior :

  • about @Latz case 1, if post_date_gmt passed to wp_insert_post is invalid, shouldn't we treat it as if it is empty or equal to 0000-00-00 00:00:00 and setting it to the current datetime while not stopping the processing of the post data by throwing a WP_Error or returning 0 ? Throwing a WP_Error or returning 0 is not the current behavior, it could produce unexpected behavior on plugins / themes / any custom code using the wp_insert_post function.
  • If we check the wordpress-develop (https://github.com/WordPress/wordpress-develop) test cases tests/phpunit/tests/post.php, function test_wp_resolve_post_date, result of @Latz case 2 seems to be the intended behavior.
 $resolved_post_date = wp_resolve_post_date( '', $invalid_date );
 $this->assertSame( '1970-01-01 00:00:00', $resolved_post_date );

Plus, in the php doc block of wp_resolve_post_date it says :

 * For back-compat purposes in wp_insert_post, an empty post_date and an invalid
 * post_date_gmt will continue to return '1970-01-01 00:00:00' rather than false.

Should we go against that ?

For information, this is the first time I've responded to a ticket and I'm not a native english speaker, so I apologize in advance if I make any mistakes regarding the rules governing these responses. Please feel free to correct me if necessary.

#5 @SirLouen
2 months ago

  • Keywords needs-patch added; needs-testing removed
  • Milestone set to Future Release

Hey @paulbonneau thanks for reporting

I think I explained it wrongly. What I really meant is that most of the logic within wp_resolve_post_date is going to be using the same logic that we might need for a patch for this.

We should keep the logic you comment for back compat, but at the same time, I think we should abstract part of the current logic within wp_resolve_post_date and use it to target both scenarios ($post_date and $post_date_gmt).

In other words: Let's try to avoid repeating any line of code twice.

#6 @paulbonneau
2 months ago

Hello @SirLouen,

First of all, thanks for your answer.
I think I was not clear and in my previous answer because it was too intricate and complicated.
To simplify : It doesn't seems possible to implement "Just like $post_date it should throw an error to give a programmer the right hint for his malfunctioning code." without introducing a breaking change that contradict the desire for backward compatibility.

I found other tests in /tests/phpunit/tests/post/wpInsertPost.php like test_insert_empty_post_date that explicitly wait 1970-01-01 00:00:00 when an invalid_date is passed in post_date_gmt. It has been introduced in this ticket : https://core.trac.wordpress.org/ticket/52187#comment:4

Nevertheless, I still have produced a patch as I think @Latz is the good way to go. This patch :

  • implements this requirement Just like $post_date it should throw an error to give a programmer the right hint for his malfunctioning code.
  • abstract part of the current logic within wp_resolve_post_date and use it to target both scenarios ($post_date and $post_date_gmt) as best as I could
  • update test so they pass when a WP_Error is thrown if an invalid post_date_gmt is passed to wp_insert_post
  • try to respect as much as possible the original logic of the code

You will find this patch name 36738-02092025.diff attached to the ticket.

#7 @SirLouen
2 months ago

  • Owner set to paulbonneau
  • Status changed from new to assigned

@paulbonneau ideally you should add a PR to the github, instead of adding just the patch here. Adding a PR to github as a PR runs a full set of unit tests and other useful checks. Also we can add code reviews straight on the code with the GitHub tool. Here on how to do this

This ticket was mentioned in PR #9705 on WordPress/wordpress-develop by @paulbonneau.


2 months ago
#8

  • Keywords has-patch has-unit-tests added; needs-patch removed

### This PR aim to :

  • implement a validation for $post_date_gmt in wp_insert_post equivalent to the existing validation for $post_date : as for $post_date validation, it interrupt the execution of wp_insert_post and return 0 or a WP_Error object if the date string isn't valid.
  • refactor and abstract part of wp_resolve_post_date
  • Update the tests to take into account the change in the principle of handling erroneous dates for post_date_gmt

#9 @pmbaldha
2 months ago

@paulbonneau You should add unit test cases in the PR: https://github.com/WordPress/wordpress-develop/pull/9705.

#10 follow-up: @paulbonneau
2 months ago

Hello @pmbaldha,

Thank for your answers !

I'm not sure I understand what you ask me to do (not a native english speaker sorry).
Do you want me to :

  1. explain textually which tests I modified in order to cover my code modification ?
  2. add more test

In case 1.

I only modified existing test. Should I explain textually what was modified and why ?

In case 2

Are you referring to a specific function or set of function I need to add test for ?
Should it cover only my addition or should I broaden the scope of the tests for this PR ?

#11 in reply to: ↑ 10 @pmbaldha
2 months ago

@paulbonneau I am requesting you to copy the unit test cases from the https://core.trac.wordpress.org/attachment/ticket/36738/36738-02092025.diff patch to the Github Pull Request https://github.com/WordPress/wordpress-develop/pull/9705/files.

The GitHub PR runs full set of unit tests and other useful checks and we can easily review the PR.

#12 @paulbonneau
2 months ago

Maybe there's something I miss here but, when I compare the patch and the PR they contain the same modification including the one on tests (you can see that in tests/phpunit/tests/post/wpInsertPost.php file on the github PR).

If I understand the WP repo PR automated process, the modified tests has already been run on my PR and validated. Don't hesitate to let me know if I misunderstood something here.

Thank for the time you took to review my answer to this ticket.

#13 @pmbaldha
2 months ago

Yes, it is my mistake. All is good now.

#14 @pmbaldha
2 months ago

Test Report

Patch tested: https://github.com/WordPress/wordpress-develop/pull/9705/

❌ This report indicates that the patch is not working as expected.

Steps to Reproduce or Test

  1. Add wp-content/mu-plugins/test.php file with the following code:
    <?php
    
    add_action('init', function() {
            if ( isset( $_GET['test'] ) && 1 == $_GET['test'] ) {
                    $post = wp_insert_post( array(
                            'post_title'    => 'Test post',
                            'post_type'      => 'post',
                            'post_status'    => 'publish',
                            'post_date_gmt'  => 'invalid_date',
                    ) );
                    var_dump( $post );
                    die;
            }
    });
    
  1. 🐞 Go to [YOUR_SITE_URL]/wp-admin/edit.php and you will see the Tes post with the 1970/01/01 at 12:00 am date as shown in the screenshot.

Expected Results

When testing a patch to validate it works as expected:

  • ✅ The post should not be inserted and should return WP_Error object.

When reproducing a bug:

  • 🐞 The post with the invalid post_date_gmt argument is inserted and show the wrong date 1970/01/01 at 12:00 am.

Environment

  • WordPress: 6.9-alpha-60093-src
  • PHP: 8.2.29
  • Server: nginx/1.29.1
  • Database: mysqli (Server: 8.4.6 / Client: mysqlnd 8.2.29)
  • Browser: Chrome 140.0.0.0
  • OS: Windows 10/11
  • Theme: Twenty Seventeen 3.9
  • MU Plugins:
    • test.php
  • Plugins:
    • Email Log 2.61
    • Test Reports 1.2.0

Actual Results

When reproducing a bug/defect:

  • 🐞 The post with the invalid post_date_gmt argument is inserted and show the wrong date 1970/01/01 at 12:00 am.

When testing the bugfix patch:

  • ❌ Issue has not resolved with patch. The post with the invalid post_date_gmt argument is returning 0, instead of WP_Error object.

#15 @SirLouen
2 months ago

@pmbaldha this was not ready for testing yet. There is no needs-testing yet ☠️
If you want a good amount of tickets that really need testing, ping me

#16 @paulbonneau
2 months ago

Hi again @pmbaldha,

You need to indicate true as the second parameter of wp_insert_post in order for this function to return a WP_Error object. If this parameter is set to false or omitted the function must return 0 in case of insertion failure.

For this reason, it does not disqualify this patch as a solution to the problem reported by @Latz.

Thanks for your tests

Note: See TracTickets for help on using tickets.