1010#include "common.h"
1111#include "path.h"
1212#include "repository.h"
13+ #include "signature.h"
1314#include "git2/config.h"
1415#include "git2/revparse.h"
1516#include "blob.h"
@@ -171,29 +172,32 @@ void git_mailmap_free(git_mailmap *mm)
171172 git__free (mm );
172173}
173174
174- int git_mailmap_add_entry (
175- git_mailmap * mm , const char * real_name , const char * real_email ,
176- const char * replace_name , const char * replace_email )
175+ static int mailmap_add_entry_unterminated (
176+ git_mailmap * mm ,
177+ const char * real_name , size_t real_name_size ,
178+ const char * real_email , size_t real_email_size ,
179+ const char * replace_name , size_t replace_name_size ,
180+ const char * replace_email , size_t replace_email_size )
177181{
178182 int error ;
179183 git_mailmap_entry * entry = git__calloc (1 , sizeof (git_mailmap_entry ));
180184 GITERR_CHECK_ALLOC (entry );
181185
182186 assert (mm && replace_email && * replace_email );
183187
184- if (real_name && * real_name ) {
185- entry -> real_name = git__strdup (real_name );
188+ if (real_name_size > 0 ) {
189+ entry -> real_name = git__substrdup (real_name , real_name_size );
186190 GITERR_CHECK_ALLOC (entry -> real_name );
187191 }
188- if (real_email && * real_email ) {
189- entry -> real_email = git__strdup (real_email );
192+ if (real_email_size > 0 ) {
193+ entry -> real_email = git__substrdup (real_email , real_email_size );
190194 GITERR_CHECK_ALLOC (entry -> real_email );
191195 }
192- if (replace_name && * replace_name ) {
193- entry -> replace_name = git__strdup (replace_name );
196+ if (replace_name_size > 0 ) {
197+ entry -> replace_name = git__substrdup (replace_name , replace_name_size );
194198 GITERR_CHECK_ALLOC (entry -> replace_name );
195199 }
196- entry -> replace_email = git__strdup (replace_email );
200+ entry -> replace_email = git__substrdup (replace_email , replace_email_size );
197201 GITERR_CHECK_ALLOC (entry -> replace_email );
198202
199203 error = git_vector_insert_sorted (& mm -> entries , entry , mailmap_entry_replace );
@@ -203,10 +207,21 @@ int git_mailmap_add_entry(
203207 return error ;
204208}
205209
206- int git_mailmap_add_buffer (git_mailmap * mm , const git_buf * buf )
210+ int git_mailmap_add_entry (
211+ git_mailmap * mm , const char * real_name , const char * real_email ,
212+ const char * replace_name , const char * replace_email )
213+ {
214+ return mailmap_add_entry_unterminated (
215+ mm ,
216+ real_name , real_name ? strlen (real_name ) : 0 ,
217+ real_email , real_email ? strlen (real_email ) : 0 ,
218+ replace_name , replace_name ? strlen (replace_name ) : 0 ,
219+ replace_email , strlen (replace_email ));
220+ }
221+
222+ int git_mailmap_add_buffer (git_mailmap * mm , const char * buf , size_t len )
207223{
208224 int error ;
209- git_mailmap_entry * entry = NULL ;
210225 git_parse_ctx ctx ;
211226
212227 /* Scratch buffers containing the real parsed names & emails */
@@ -215,10 +230,15 @@ int git_mailmap_add_buffer(git_mailmap *mm, const git_buf *buf)
215230 git_buf replace_name = GIT_BUF_INIT ;
216231 git_buf replace_email = GIT_BUF_INIT ;
217232
218- if (git_buf_contains_nul (buf ))
233+ /* If `len` is passed as 0, use strlen to get the real length */
234+ if (buf && len == 0 )
235+ len = strlen (buf );
236+
237+ /* Buffers may not contain '\0's. */
238+ if (memchr (buf , '\0' , len ) != NULL )
219239 return -1 ;
220240
221- git_parse_ctx_init (& ctx , buf -> ptr , buf -> size );
241+ git_parse_ctx_init (& ctx , buf , len );
222242
223243 /* Run the parser */
224244 while (ctx .remain_len > 0 ) {
@@ -230,51 +250,31 @@ int git_mailmap_add_buffer(git_mailmap *mm, const git_buf *buf)
230250 continue ; /* TODO: warn */
231251 }
232252
233- entry = git__calloc (1 , sizeof (git_mailmap_entry ));
234- GITERR_CHECK_ALLOC (entry );
235-
236- if (real_name .size > 0 ) {
237- entry -> real_name = git__substrdup (real_name .ptr , real_name .size );
238- GITERR_CHECK_ALLOC (entry -> real_name );
239- }
240- if (real_email .size > 0 ) {
241- entry -> real_email = git__substrdup (real_email .ptr , real_email .size );
242- GITERR_CHECK_ALLOC (entry -> real_email );
243- }
244- if (replace_name .size > 0 ) {
245- entry -> replace_name = git__substrdup (replace_name .ptr , replace_name .size );
246- GITERR_CHECK_ALLOC (entry -> replace_name );
247- }
248- entry -> replace_email = git__substrdup (replace_email .ptr , replace_email .size );
249- GITERR_CHECK_ALLOC (entry -> replace_email );
250-
251- error = git_vector_insert_sorted (
252- & mm -> entries , entry , mailmap_entry_replace );
253+ /* NOTE: Can't use add_entry(...) as our buffers aren't terminated */
254+ error = mailmap_add_entry_unterminated (
255+ mm , real_name .ptr , real_name .size , real_email .ptr , real_email .size ,
256+ replace_name .ptr , replace_name .size , replace_email .ptr , replace_email .size );
253257 if (error < 0 && error != GIT_EEXISTS )
254258 goto cleanup ;
255259
256- entry = NULL ;
257260 error = 0 ;
258261 }
259262
260263cleanup :
261- mailmap_entry_free (entry );
262-
263- /* We never allocate data in these buffers, but better safe than sorry */
264264 git_buf_free (& real_name );
265265 git_buf_free (& real_email );
266266 git_buf_free (& replace_name );
267267 git_buf_free (& replace_email );
268268 return error ;
269269}
270270
271- int git_mailmap_from_buffer (git_mailmap * * out , const git_buf * buffer )
271+ int git_mailmap_from_buffer (git_mailmap * * out , const char * data , size_t len )
272272{
273273 int error = git_mailmap_new (out );
274274 if (error < 0 )
275275 return error ;
276276
277- error = git_mailmap_add_buffer (* out , buffer );
277+ error = git_mailmap_add_buffer (* out , data , len );
278278 if (error < 0 ) {
279279 git_mailmap_free (* out );
280280 * out = NULL ;
@@ -283,7 +283,7 @@ int git_mailmap_from_buffer(git_mailmap **out, const git_buf *buffer)
283283}
284284
285285static int mailmap_add_blob (
286- git_mailmap * mm , git_repository * repo , const char * spec )
286+ git_mailmap * mm , git_repository * repo , const char * rev )
287287{
288288 git_object * object = NULL ;
289289 git_blob * blob = NULL ;
@@ -292,7 +292,7 @@ static int mailmap_add_blob(
292292
293293 assert (mm && repo );
294294
295- error = git_revparse_single (& object , repo , spec );
295+ error = git_revparse_single (& object , repo , rev );
296296 if (error < 0 )
297297 goto cleanup ;
298298
@@ -304,7 +304,7 @@ static int mailmap_add_blob(
304304 if (error < 0 )
305305 goto cleanup ;
306306
307- error = git_mailmap_add_buffer (mm , & content );
307+ error = git_mailmap_add_buffer (mm , content . ptr , content . size );
308308 if (error < 0 )
309309 goto cleanup ;
310310
@@ -331,7 +331,7 @@ static int mailmap_add_file_ondisk(
331331 if (error < 0 )
332332 goto cleanup ;
333333
334- error = git_mailmap_add_buffer (mm , & content );
334+ error = git_mailmap_add_buffer (mm , content . ptr , content . size );
335335 if (error < 0 )
336336 goto cleanup ;
337337
@@ -345,21 +345,21 @@ static int mailmap_add_file_ondisk(
345345static void mailmap_add_from_repository (git_mailmap * mm , git_repository * repo )
346346{
347347 git_config * config = NULL ;
348- git_buf spec_buf = GIT_BUF_INIT ;
348+ git_buf rev_buf = GIT_BUF_INIT ;
349349 git_buf path_buf = GIT_BUF_INIT ;
350- const char * spec = NULL ;
350+ const char * rev = NULL ;
351351 const char * path = NULL ;
352352
353353 assert (mm && repo );
354354
355355 /* If we're in a bare repo, default blob to 'HEAD:.mailmap' */
356356 if (repo -> is_bare )
357- spec = MM_BLOB_DEFAULT ;
357+ rev = MM_BLOB_DEFAULT ;
358358
359359 /* Try to load 'mailmap.file' and 'mailmap.blob' cfgs from the repo */
360360 if (git_repository_config (& config , repo ) == 0 ) {
361- if (git_config_get_string_buf (& spec_buf , config , MM_BLOB_CONFIG ) == 0 )
362- spec = spec_buf .ptr ;
361+ if (git_config_get_string_buf (& rev_buf , config , MM_BLOB_CONFIG ) == 0 )
362+ rev = rev_buf .ptr ;
363363 if (git_config_get_path (& path_buf , config , MM_FILE_CONFIG ) == 0 )
364364 path = path_buf .ptr ;
365365 }
@@ -377,12 +377,12 @@ static void mailmap_add_from_repository(git_mailmap *mm, git_repository *repo)
377377 */
378378 if (!repo -> is_bare )
379379 mailmap_add_file_ondisk (mm , MM_FILE , repo );
380- if (spec != NULL )
381- mailmap_add_blob (mm , repo , spec );
380+ if (rev != NULL )
381+ mailmap_add_blob (mm , repo , rev );
382382 if (path != NULL )
383383 mailmap_add_file_ondisk (mm , path , repo );
384384
385- git_buf_free (& spec_buf );
385+ git_buf_free (& rev_buf );
386386 git_buf_free (& path_buf );
387387 git_config_free (config );
388388}
@@ -403,7 +403,10 @@ const git_mailmap_entry *git_mailmap_entry_lookup(
403403 ssize_t fallback = -1 ;
404404 size_t idx ;
405405 git_mailmap_entry * entry ;
406- git_mailmap_entry needle = { NULL , NULL , NULL , (char * )email };
406+
407+ /* The lookup needle we want to use only sets the replace_email. */
408+ git_mailmap_entry needle = { NULL };
409+ needle .replace_email = (char * )email ;
407410
408411 assert (email );
409412
@@ -457,3 +460,26 @@ int git_mailmap_resolve(
457460 }
458461 return 0 ;
459462}
463+
464+ int git_mailmap_resolve_signature (
465+ git_signature * * out , const git_mailmap * mailmap , const git_signature * sig )
466+ {
467+ const char * name = NULL ;
468+ const char * email = NULL ;
469+ int error ;
470+
471+ if (!sig )
472+ return 0 ;
473+
474+ error = git_mailmap_resolve (& name , & email , mailmap , sig -> name , sig -> email );
475+ if (error < 0 )
476+ return error ;
477+
478+ error = git_signature_new (out , name , email , sig -> when .time , sig -> when .offset );
479+ if (error < 0 )
480+ return error ;
481+
482+ /* Copy over the sign, as git_signature_new doesn't let you pass it. */
483+ (* out )-> when .sign = sig -> when .sign ;
484+ return 0 ;
485+ }
0 commit comments