summaryrefslogtreecommitdiffabout
path: root/cgit.c
authorLars Hjemli <hjemli@gmail.com>2009-01-11 20:23:04 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2009-01-11 20:23:04 (UTC)
commiteb14609dc46461728a065c0a243b338fc32fd762 (patch) (unidiff)
treef00563342db8859f46ac8141fdaa5d4e17eb940e /cgit.c
parent720b6ece90900df9f836a45d8e7f1cd56f62400a (diff)
downloadcgit-eb14609dc46461728a065c0a243b338fc32fd762.zip
cgit-eb14609dc46461728a065c0a243b338fc32fd762.tar.gz
cgit-eb14609dc46461728a065c0a243b338fc32fd762.tar.bz2
Avoid SEGFAULT on invalid requests
When an unknown page is requested, either on the querystring or via PATH_INFO, we end up with a null-referencing cgit_cmd. This null- pointer is then used as argument to the hc() function (which decides what tab to render as 'active'), but this function failed to check if a valid cmd was specified and a SEGFAULT would occur. This patch fixes the issue by introducing a 'fallback-cmd' which specifies what tab to render as 'active' when no valid cmd is requested. While at it, we now also keep track of the active repository even if an invalid cmd was requested since we want to show the error message about the invalid request in the correct context. Noticed-by: Robin Redeker <elmex@ta-sa.org> Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (limited to 'cgit.c') (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.c1
1 files changed, 0 insertions, 1 deletions
diff --git a/cgit.c b/cgit.c
index c82587b..6e5215e 100644
--- a/cgit.c
+++ b/cgit.c
@@ -196,193 +196,192 @@ static void prepare_context(struct cgit_context *ctx)
196 196
197struct refmatch { 197struct refmatch {
198 char *req_ref; 198 char *req_ref;
199 char *first_ref; 199 char *first_ref;
200 int match; 200 int match;
201}; 201};
202 202
203int find_current_ref(const char *refname, const unsigned char *sha1, 203int find_current_ref(const char *refname, const unsigned char *sha1,
204 int flags, void *cb_data) 204 int flags, void *cb_data)
205{ 205{
206 struct refmatch *info; 206 struct refmatch *info;
207 207
208 info = (struct refmatch *)cb_data; 208 info = (struct refmatch *)cb_data;
209 if (!strcmp(refname, info->req_ref)) 209 if (!strcmp(refname, info->req_ref))
210 info->match = 1; 210 info->match = 1;
211 if (!info->first_ref) 211 if (!info->first_ref)
212 info->first_ref = xstrdup(refname); 212 info->first_ref = xstrdup(refname);
213 return info->match; 213 return info->match;
214} 214}
215 215
216char *find_default_branch(struct cgit_repo *repo) 216char *find_default_branch(struct cgit_repo *repo)
217{ 217{
218 struct refmatch info; 218 struct refmatch info;
219 char *ref; 219 char *ref;
220 220
221 info.req_ref = repo->defbranch; 221 info.req_ref = repo->defbranch;
222 info.first_ref = NULL; 222 info.first_ref = NULL;
223 info.match = 0; 223 info.match = 0;
224 for_each_branch_ref(find_current_ref, &info); 224 for_each_branch_ref(find_current_ref, &info);
225 if (info.match) 225 if (info.match)
226 ref = info.req_ref; 226 ref = info.req_ref;
227 else 227 else
228 ref = info.first_ref; 228 ref = info.first_ref;
229 if (ref) 229 if (ref)
230 ref = xstrdup(ref); 230 ref = xstrdup(ref);
231 return ref; 231 return ref;
232} 232}
233 233
234static int prepare_repo_cmd(struct cgit_context *ctx) 234static int prepare_repo_cmd(struct cgit_context *ctx)
235{ 235{
236 char *tmp; 236 char *tmp;
237 unsigned char sha1[20]; 237 unsigned char sha1[20];
238 int nongit = 0; 238 int nongit = 0;
239 239
240 setenv("GIT_DIR", ctx->repo->path, 1); 240 setenv("GIT_DIR", ctx->repo->path, 1);
241 setup_git_directory_gently(&nongit); 241 setup_git_directory_gently(&nongit);
242 if (nongit) { 242 if (nongit) {
243 ctx->page.title = fmt("%s - %s", ctx->cfg.root_title, 243 ctx->page.title = fmt("%s - %s", ctx->cfg.root_title,
244 "config error"); 244 "config error");
245 tmp = fmt("Not a git repository: '%s'", ctx->repo->path); 245 tmp = fmt("Not a git repository: '%s'", ctx->repo->path);
246 ctx->repo = NULL; 246 ctx->repo = NULL;
247 cgit_print_http_headers(ctx); 247 cgit_print_http_headers(ctx);
248 cgit_print_docstart(ctx); 248 cgit_print_docstart(ctx);
249 cgit_print_pageheader(ctx); 249 cgit_print_pageheader(ctx);
250 cgit_print_error(tmp); 250 cgit_print_error(tmp);
251 cgit_print_docend(); 251 cgit_print_docend();
252 return 1; 252 return 1;
253 } 253 }
254 ctx->page.title = fmt("%s - %s", ctx->repo->name, ctx->repo->desc); 254 ctx->page.title = fmt("%s - %s", ctx->repo->name, ctx->repo->desc);
255 255
256 if (!ctx->qry.head) { 256 if (!ctx->qry.head) {
257 ctx->qry.nohead = 1; 257 ctx->qry.nohead = 1;
258 ctx->qry.head = find_default_branch(ctx->repo); 258 ctx->qry.head = find_default_branch(ctx->repo);
259 ctx->repo->defbranch = ctx->qry.head; 259 ctx->repo->defbranch = ctx->qry.head;
260 } 260 }
261 261
262 if (!ctx->qry.head) { 262 if (!ctx->qry.head) {
263 cgit_print_http_headers(ctx); 263 cgit_print_http_headers(ctx);
264 cgit_print_docstart(ctx); 264 cgit_print_docstart(ctx);
265 cgit_print_pageheader(ctx); 265 cgit_print_pageheader(ctx);
266 cgit_print_error("Repository seems to be empty"); 266 cgit_print_error("Repository seems to be empty");
267 cgit_print_docend(); 267 cgit_print_docend();
268 return 1; 268 return 1;
269 } 269 }
270 270
271 if (get_sha1(ctx->qry.head, sha1)) { 271 if (get_sha1(ctx->qry.head, sha1)) {
272 tmp = xstrdup(ctx->qry.head); 272 tmp = xstrdup(ctx->qry.head);
273 ctx->qry.head = ctx->repo->defbranch; 273 ctx->qry.head = ctx->repo->defbranch;
274 cgit_print_http_headers(ctx); 274 cgit_print_http_headers(ctx);
275 cgit_print_docstart(ctx); 275 cgit_print_docstart(ctx);
276 cgit_print_pageheader(ctx); 276 cgit_print_pageheader(ctx);
277 cgit_print_error(fmt("Invalid branch: %s", tmp)); 277 cgit_print_error(fmt("Invalid branch: %s", tmp));
278 cgit_print_docend(); 278 cgit_print_docend();
279 return 1; 279 return 1;
280 } 280 }
281 return 0; 281 return 0;
282} 282}
283 283
284static void process_request(void *cbdata) 284static void process_request(void *cbdata)
285{ 285{
286 struct cgit_context *ctx = cbdata; 286 struct cgit_context *ctx = cbdata;
287 struct cgit_cmd *cmd; 287 struct cgit_cmd *cmd;
288 288
289 cmd = cgit_get_cmd(ctx); 289 cmd = cgit_get_cmd(ctx);
290 if (!cmd) { 290 if (!cmd) {
291 ctx->page.title = "cgit error"; 291 ctx->page.title = "cgit error";
292 ctx->repo = NULL;
293 cgit_print_http_headers(ctx); 292 cgit_print_http_headers(ctx);
294 cgit_print_docstart(ctx); 293 cgit_print_docstart(ctx);
295 cgit_print_pageheader(ctx); 294 cgit_print_pageheader(ctx);
296 cgit_print_error("Invalid request"); 295 cgit_print_error("Invalid request");
297 cgit_print_docend(); 296 cgit_print_docend();
298 return; 297 return;
299 } 298 }
300 299
301 if (cmd->want_repo && !ctx->repo) { 300 if (cmd->want_repo && !ctx->repo) {
302 cgit_print_http_headers(ctx); 301 cgit_print_http_headers(ctx);
303 cgit_print_docstart(ctx); 302 cgit_print_docstart(ctx);
304 cgit_print_pageheader(ctx); 303 cgit_print_pageheader(ctx);
305 cgit_print_error(fmt("No repository selected")); 304 cgit_print_error(fmt("No repository selected"));
306 cgit_print_docend(); 305 cgit_print_docend();
307 return; 306 return;
308 } 307 }
309 308
310 if (ctx->repo && prepare_repo_cmd(ctx)) 309 if (ctx->repo && prepare_repo_cmd(ctx))
311 return; 310 return;
312 311
313 if (cmd->want_layout) { 312 if (cmd->want_layout) {
314 cgit_print_http_headers(ctx); 313 cgit_print_http_headers(ctx);
315 cgit_print_docstart(ctx); 314 cgit_print_docstart(ctx);
316 cgit_print_pageheader(ctx); 315 cgit_print_pageheader(ctx);
317 } 316 }
318 317
319 cmd->fn(ctx); 318 cmd->fn(ctx);
320 319
321 if (cmd->want_layout) 320 if (cmd->want_layout)
322 cgit_print_docend(); 321 cgit_print_docend();
323} 322}
324 323
325int cmp_repos(const void *a, const void *b) 324int cmp_repos(const void *a, const void *b)
326{ 325{
327 const struct cgit_repo *ra = a, *rb = b; 326 const struct cgit_repo *ra = a, *rb = b;
328 return strcmp(ra->url, rb->url); 327 return strcmp(ra->url, rb->url);
329} 328}
330 329
331void print_repo(struct cgit_repo *repo) 330void print_repo(struct cgit_repo *repo)
332{ 331{
333 printf("repo.url=%s\n", repo->url); 332 printf("repo.url=%s\n", repo->url);
334 printf("repo.name=%s\n", repo->name); 333 printf("repo.name=%s\n", repo->name);
335 printf("repo.path=%s\n", repo->path); 334 printf("repo.path=%s\n", repo->path);
336 if (repo->owner) 335 if (repo->owner)
337 printf("repo.owner=%s\n", repo->owner); 336 printf("repo.owner=%s\n", repo->owner);
338 if (repo->desc) 337 if (repo->desc)
339 printf("repo.desc=%s\n", repo->desc); 338 printf("repo.desc=%s\n", repo->desc);
340 if (repo->readme) 339 if (repo->readme)
341 printf("repo.readme=%s\n", repo->readme); 340 printf("repo.readme=%s\n", repo->readme);
342 printf("\n"); 341 printf("\n");
343} 342}
344 343
345void print_repolist(struct cgit_repolist *list) 344void print_repolist(struct cgit_repolist *list)
346{ 345{
347 int i; 346 int i;
348 347
349 for(i = 0; i < list->count; i++) 348 for(i = 0; i < list->count; i++)
350 print_repo(&list->repos[i]); 349 print_repo(&list->repos[i]);
351} 350}
352 351
353 352
354static void cgit_parse_args(int argc, const char **argv) 353static void cgit_parse_args(int argc, const char **argv)
355{ 354{
356 int i; 355 int i;
357 int scan = 0; 356 int scan = 0;
358 357
359 for (i = 1; i < argc; i++) { 358 for (i = 1; i < argc; i++) {
360 if (!strncmp(argv[i], "--cache=", 8)) { 359 if (!strncmp(argv[i], "--cache=", 8)) {
361 ctx.cfg.cache_root = xstrdup(argv[i]+8); 360 ctx.cfg.cache_root = xstrdup(argv[i]+8);
362 } 361 }
363 if (!strcmp(argv[i], "--nocache")) { 362 if (!strcmp(argv[i], "--nocache")) {
364 ctx.cfg.nocache = 1; 363 ctx.cfg.nocache = 1;
365 } 364 }
366 if (!strncmp(argv[i], "--query=", 8)) { 365 if (!strncmp(argv[i], "--query=", 8)) {
367 ctx.qry.raw = xstrdup(argv[i]+8); 366 ctx.qry.raw = xstrdup(argv[i]+8);
368 } 367 }
369 if (!strncmp(argv[i], "--repo=", 7)) { 368 if (!strncmp(argv[i], "--repo=", 7)) {
370 ctx.qry.repo = xstrdup(argv[i]+7); 369 ctx.qry.repo = xstrdup(argv[i]+7);
371 } 370 }
372 if (!strncmp(argv[i], "--page=", 7)) { 371 if (!strncmp(argv[i], "--page=", 7)) {
373 ctx.qry.page = xstrdup(argv[i]+7); 372 ctx.qry.page = xstrdup(argv[i]+7);
374 } 373 }
375 if (!strncmp(argv[i], "--head=", 7)) { 374 if (!strncmp(argv[i], "--head=", 7)) {
376 ctx.qry.head = xstrdup(argv[i]+7); 375 ctx.qry.head = xstrdup(argv[i]+7);
377 ctx.qry.has_symref = 1; 376 ctx.qry.has_symref = 1;
378 } 377 }
379 if (!strncmp(argv[i], "--sha1=", 7)) { 378 if (!strncmp(argv[i], "--sha1=", 7)) {
380 ctx.qry.sha1 = xstrdup(argv[i]+7); 379 ctx.qry.sha1 = xstrdup(argv[i]+7);
381 ctx.qry.has_sha1 = 1; 380 ctx.qry.has_sha1 = 1;
382 } 381 }
383 if (!strncmp(argv[i], "--ofs=", 6)) { 382 if (!strncmp(argv[i], "--ofs=", 6)) {
384 ctx.qry.ofs = atoi(argv[i]+6); 383 ctx.qry.ofs = atoi(argv[i]+6);
385 } 384 }
386 if (!strncmp(argv[i], "--scan-tree=", 12)) { 385 if (!strncmp(argv[i], "--scan-tree=", 12)) {
387 scan++; 386 scan++;
388 scan_tree(argv[i] + 12); 387 scan_tree(argv[i] + 12);